• 静态代理与动态代理


      代理是一种设计模式,它提供了对目标对象的另外的访问方式,通过代理访问目标对象,可以在目标对象实现的基础上增加额外的功能操作,扩展目标对象的功能。

    1.动态代理

    1)代理对象,不需要实现接口;

    2)代理对象的生成,是利用JDKAPI, 动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型;);

    3)  动态代理, JDK代理, 接口代理;

    public class ProxyFactory {
        private Object target;
        public ProxyFactory(Object target){
            this.target = target;
        }
        //给目标对象生成代理对象
        public Object getProxyInstance(){
            return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),
                    this.target.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("开启事务");
                            System.out.println(method.getName());
                            Object result = method.invoke(target,args);
                            System.out.println("结束事务");
                            return result;
                        }
                    });
        }
    }

    使用动态代理

            UserDao userDao = new UserDao();
            ProxyFactory proxyFactory = new ProxyFactory(userDao);
            //强转,注意必须用接口类型接受
            IUserDao proxyInstance = (IUserDao) proxyFactory.getProxyInstance();
            proxyInstance.save();

    生成的代理对象的类名类似于class com.sun.proxy.$Proxy4,为动态代理。

    动态代理要求目标对象必须要实现接口,如果目标对象没有实现接口,需要用到cglib代理。

    2.cglib代理

      CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。

      CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

    1) 需要引入cglib – jar文件, 但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。

    2)引入功能包后,就可以在内存中动态构建子类

    3)代理的类不能为final, 否则报错。

    4) 目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。

    public class ProxyFactory implements MethodInterceptor{
        private  Object target;
        public ProxyFactory(Object target){
            this.target = target;
        }
        public Object getProxyInstance(){
            //工具类
            Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass(target.getClass());
            //设置回调函数
            enhancer.setCallback(this);
            return enhancer.create();
        }
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("开始事务");
            Object result = method.invoke(target, objects);
            System.out.println("结束事务");
            return result;
        }
    }

    使用cglib代理

            UserDao userDao = new UserDao();
            UserDao proxy = (UserDao) new ProxyFactory(userDao).getProxyInstance();
            proxy.save();

    生成的代理对象类名类似于class com.juaner.proxy.cglib.UserDao$$EnhancerByCGLIB$$aa5d198b。

    在Spring的AOP编程中,

             如果加入容器的目标对象有实现接口,用JDK代理;

             如果目标对象没有实现接口,用Cglib代理;

  • 相关阅读:
    mac 系统下删除目录的所有.svn文件
    java DES加密解密文件
    也许,未来需要重新规划
    android选择图片或拍照图片上传到服务器(包括上传参数)
    iOS DES ECB模式对称加密解密
    iOS开发中防止键盘挡住UITextField解决方案
    xCode 4.X 免证书真机公布及调试
    iOS 获取手机的型号,系统版本,软件名称,软件版本
    java DES ECB模式对称加密解密
    解决error: failed to launch"/private/var/mobile/Applications/XX" timed out waiting for app to launch
  • 原文地址:https://www.cnblogs.com/juaner767/p/5595654.html
Copyright © 2020-2023  润新知