Java动态代理
参考:http://www.360doc.com/content/14/0618/11/454045_387708106.shtml
http://blog.csdn.net/heyutao007/article/details/49738887
推荐:http://paddy-w.iteye.com/blog/841798
JAVA的动态代理
代理模式
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
动态代理的两种实现:
1.JDK动态代理。
2.CGLIB动态代理。
两种实现比较:
jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
1.JDK动态代理demo
1 package proxy; 2 3 public interface UserService { 4 5 public String getName(int name); 6 7 public Integer getAge(int age); 8 9 }
1 package proxy; 2 3 public class UserServiceImpl implements UserService { 4 5 @Override 6 public String getName(int name) { 7 // TODO Auto-generated method stub 8 System.out.println("----- getName -----"); 9 return "Tom"; 10 } 11 12 @Override 13 public Integer getAge(int age) { 14 // TODO Auto-generated method stub 15 System.out.println("----- getAge -----"); 16 return 10; 17 } 18 }
1 package proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class MyInvocationHandler implements InvocationHandler { 7 8 private Object target; 9 10 public MyInvocationHandler() { 11 // TODO Auto-generated constructor stub 12 super(); 13 } 14 15 public MyInvocationHandler(Object target) { 16 this.target = target; 17 } 18 19 @Override 20 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 21 // TODO Auto-generated method stub 22 if("getName".equals(method.getName())) { 23 System.out.println("+++++ before " + method.getName() + " +++++"); 24 Object result = method.invoke(target, args); 25 System.out.println("+++++ after " + method.getName() + " +++++"); 26 return result; 27 } else { 28 Object result = method.invoke(target, args); 29 return result; 30 } 31 } 32 33 }
1 package proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Proxy; 5 6 public class Main1 { 7 8 public static void main(String[] args) { 9 UserService userService = new UserServiceImpl(); 10 InvocationHandler invocationHandler = new MyInvocationHandler(userService); 11 UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler); 12 System.out.println(userServiceProxy.getName(1)); 13 System.out.println(userServiceProxy.getAge(1)); 14 } 15 16 }
2.CGLIB动态代理demo
1 package proxy; 2 3 import java.lang.reflect.Method; 4 5 import net.sf.cglib.proxy.MethodInterceptor; 6 import net.sf.cglib.proxy.MethodProxy; 7 8 public class CglibProxy implements MethodInterceptor { 9 10 @Override 11 public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 12 System.out.println("++++++before " + methodProxy.getSuperName() + "++++++"); 13 System.out.println(method.getName()); 14 Object o1 = methodProxy.invokeSuper(o, args); 15 System.out.println("++++++before " + methodProxy.getSuperName() + "++++++"); 16 return o1; 17 } 18 }
1 package proxy; 2 3 import net.sf.cglib.proxy.Enhancer; 4 5 public class Main2 { 6 7 public static void main(String[] args) { 8 CglibProxy cglibProxy = new CglibProxy(); 9 10 Enhancer enhancer = new Enhancer(); 11 enhancer.setSuperclass(UserServiceImpl.class); 12 enhancer.setCallback(cglibProxy); 13 14 UserService o = (UserService)enhancer.create(); 15 o.getName(1); 16 o.getAge(1); 17 } 18 19 }
参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。
参考:https://segmentfault.com/q/1010000002652067
为什么cglib不能拦截静态方法是因为Cglib的实现方式:生成的代理类继承自被代理类/目标类,请求时,执行自己织入的增强,然后再执行目标方法,因而使用继承方式创建代理类不能代理任何final方法和类,以及静态方法。