Spring中AOP实现的两种方式之JDK和cglib的动态代理
2016-08-31 20:03
1291 查看
AOP的实现原理: 都是基于代理模式,都是生成一个大代理对象 静态AOP: AspectJ实现的AOP, 将切面代码直接编译到Java类文件中 --- 实现: JDK提供的动态代理技术 动态AOP: 将切面代码进行动态织入实现的AOP --- Spring的AOP为动态AOP --- 实现: CGLIB(动态字节码增强技术) JDK动态代理: --- InvocationHandler 和 Proxy.newProxyInstance() --- 动态代理的基本原理为反射 + 多态 + 聚合 InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。 Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象 JDK动态代理要求被代理者实现一个接口,只有接口中的方法才能被代理, 其方法是,将被代理对象注入到一个中间对象,而中间对象实现InvocationHandler接口, 在实现该接口时,可以在被代理对象调用它的方法时,在调用前后插入一些代码, Proxy.newProxyInstance()能够利用中间对象来生产代理对象,插入的代码就是切面代码 局限: 被代理的对象必须实现接口,而且只有接口中的方法才能被代理 --- 实例:com.jay.advanced.java.动态代理.demo1 eg: public class MyProxyInvocationHandler implements InvocationHandler { private Object target; // 被代理的对象 public MyProxyInvocationHandler(Object target) { this.target = target; } public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } /* * 动态代理,执行被代理的方法 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在目标对象的方法执行之前简单的打印一下 System.out.println("------------------before------------------"); // 执行目标对象的方法 Object result = method.invoke(target, args); // 在目标对象的方法执行之后简单的打印一下 System.out.println("-------------------after------------------"); return result; } /* * 获取代理对象 */ public Object getProxy(){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this); } } 测试: public class Test { public static void main(String args[]){ //实例化目标对象 --- 被代理对象 Object proxyedObj = new UserServiceImpl(); //实例化中间对象 MyProxyInvocationHandler proxyInvocationHandler = new MyProxyInvocationHandler(proxyedObj); //根据目标对象 生成 代理对象, 对目标对象的接口进行代理::UserServiceImpl.class.getInterfaces() UserService proxyObj = (UserService) proxyInvocationHandler.getProxy(); //调用代理对象的方法 proxyObj.addUser(new User()); proxyObj.getUser(1); } } cglib动态代理:--- 字节码生成技术 实现 MethodInterceptor接口,重写其 interceptor()方法 CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑 继承被代理对象,然后重写被代理的方法,在覆盖该方法时,插入自己的代码, 因为需要重写被代理对象的方法,要求:被代理的方法不能使final方法,因为final方法不能被覆盖 eg: public class CglibProxy implements MethodInterceptor { private Object target; // 被代理对象 public CglibProxy(Object target){ this.target = target; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy proxy) throws Throwable { System.out.println("do sth before...."); Object result = proxy.invokeSuper(o, objects); System.out.println("do sth after...."); return result; } public Object getProxyObject() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 设置父类 // 设置回调 enhancer.setCallback(this); // 在调用父类方法时,回调 this.intercept() // 创建代理对象 return enhancer.create(); } } 测试: public class Test { public static void main(String[] args){ Object proxyedObject = new UserServiceImpl(); // 被代理的对象 CglibProxy cgProxy = new CglibProxy(proxyedObject); UserService proxyObject = (UserService) cgProxy.getProxyObject(); proxyObject.getUser(1); proxyObject.addUser(new User()); } } 2种方式对比: CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多, 所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。 同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理! CGLib所创建的动态代理对象的性能比JDK所创建的代理对象性能高不少,大概10倍,但CGLib在创建代理对象时所花费的时间却比JDK动态代理多大概8倍, 所以对于singleton的代理对象或者具有实例池的代理,因为无需频繁的创建新的实例,所以比较适合CGLib动态代理技术,反之则适用于JDK动态代理技术。 另外,由于CGLib采用动态创建子类的方式生成代理对象,所以不能对目标类中的final,private等方法进行处理 默认情况下,Spring AOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的代理使用CGLIB来实现
Spring中的动态代理的使用
Spring定义了org.springframework.aop.framework.AopProxy接口,并提供了如下两种final类型的实现类:
关于Spring中选择代理类型的判断
如果通过ProxyFactory的setInterfaces(Class[] interfaces)指定针对接口进行代理,ProxyFactory就使用JdkDynamicAopProxy,如果是针对类的代理,则使用Cglib2AopProxy。另外,如果使用ProxyFactory的setOptimize(true)方法,则启动了优化代理方式,这样针对接口的代理也会使用Cglib2AopProxy。
在引介增强中就需要强制指定为Cglib2AopProxy,因为引介增强是一种比较特殊的增强类型,不是在目标周围织入增强,而是为目标类创建新的方法和属性,所以引介增强的连接点事类级别的。而非方法级别的。
参考:
http://www.cnblogs.com/hujunzheng/category/598702.html http://blog.csdn.net/jialinqiang/article/details/8950989 http://rejoy.iteye.com/blog/1627405 http://blog.csdn.net/mhmyqn/article/details/48474815 http://my.oschina.net/JoeyXieIsCool/blog/608420 http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html
相关文章推荐
- Spring AOP 代理实现的两种方式: JDK动态代理 和 Cglib框架动态代理
- Spring中AOP实现的两种方式之JDK和cglib的动态代理
- Spring系列之 (十一):AOP实现方式:动态代理的两个方式(JDK和Cglib)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- 模拟spring,Aop(JDK与CGLib两种方式实现)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- spring(AOP)静态代理、JDK动态代理、cglib实现代理
- 静态代理、JDK动态代理、CGLIB动态代理、Spring实现AOP、IOC+AOP
- 动态代理及其两种实现方式(JDK、CGLIB)
- Spring的两种代理方式:JDK动态代理和CGLIB动态代理
- spring02 注解方式实现MVC、spring的继承、代理模式(静/动) :jdk动态代理,cglib动态代理
- 转:Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理-转载
- spring实现AOP的两种方式以及实现动态代理方式
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- 实现动态代理的两种方式介绍+例子demo(JDK、CGlib)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- 动态代理的两种实现方式(JDK/Cglib)
- Spring—AOP两种代理机制对比(JDK和CGLib动态代理)