代理模式在我们的应用中是很常见的,例如拦截器,spring的事务管理等。之所以能被代理,是因为java允许我们通过反射机制动态构造目标对象,并调用相应的方法。
就好像拿到了目标对象的引用,自然可以在目标对象方法执行前后处理一些自己的任务,例如日志服务拦截器,防止重复提交拦截器等。
1.java的静态代理(纯粹是拿到目标的引用,调用目标方法)
1 public interface Hello { 2 public void say(String name); 3 } 4 public class HelloImpl implements Hello{ 5 @Override 6 public void say(String name) { 7 System.out.println("Hello!" + name); 8 } 9 } 10 public class HelloProxy implements Hello{ 11 private Hello hello; 12 public HelloProxy() { 13 hello = new HelloImpl(); 14 } 15 @Override 16 public void say(String name) { 17 before(); 18 hello.say(name); 19 after(); 20 } 21 private void before() { 22 System.out.println("before......"); 23 } 24 private void after() { 25 System.out.println("after......"); 26 } 27 public static void main(String[] args) { 28 new HelloProxy().say("麦德漂"); 29 } 30 }
静态的代理,就是讲目标对象做了一层包装,然后调用目标对象的对应方法。
2.java的动态代理(基于接口的代理)
1 public class DynamicProxy implements InvocationHandler { 2 3 private Object target; 4 5 public DynamicProxy(Object target) { 6 super(); 7 this.target = target; 8 } 9 10 @Override 11 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 12 return method.invoke(target, args); 13 } 14 15 public static void main(String[] args) { 16 Hello hello = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), new Class[]{Hello.class},new DynamicProxy(new HelloImpl())); 17 hello.say("麦德漂"); 18 } 19 }
动态代理相对于静态代理已经方便了很多,不用再去写单独的代理类,只是基于接口才能生效。
3.cglib代理(用过Hibernate的同学一定看到过cglib的身影)
1 public class CGLibProxy implements MethodInterceptor{ 2 3 public Object getProxy(Object target) { 4 return Enhancer.create(target.getClass(), this); 5 } 6 7 @Override 8 public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 9 return methodProxy.invokeSuper(obj, args); 10 } 11 12 public static void main(String[] args) { 13 Hello hello = (Hello)new CGLibProxy().getProxy(new HelloImpl()); 14 hello.say("麦德漂"); 15 } 16 17 }
不再基于接口,强大的高性能生成代码工具。