静态代理没有什么好说的,不断的写新的类,实现与被代理类一样的接口,从而来拓展功能。缺点太多,如接口变化,就要重写新的代理类。
动态代理使用最多的可能就是传说中的aop了。它解决了静态代理的缺点,即使接口变化了,代理类也不需要变化。动态代理实现方式主要有两种:1、jdk自带的 2、cglib技术
个人觉得代理模式的用处就是在不对原有类进行修改的情况下,对类的功能进行增强。有前置增强、后置增强、环绕增强、抛出增强、引入增强等。其中前四种增强是对类的方法的增强,叫做织入(Weaving),抛出增强可以对异常进行处理。引入增强是对类进行增强,如给类添加新的方法等。
接口:
public interface HelloWorld { void say(); }被代理类:
public class Hello implements HelloWorld { @Override public void say() { System.out.println("Hello World"); } }动态代理类:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JdkDynamicProxy { private static class HelloWorldDynamicProxy implements InvocationHandler{ Object target; public HelloWorldDynamicProxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Hello Dota"); method.invoke(target, args); System.out.println("Hello Dota2"); return null; } //Object像下转型为T,会有警告,这里利用了泛型,否则调用完的结果还需要强制转换 @SuppressWarnings("unchecked") public <T> T getProxy(){ return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } } public static void main(String args[]){ Hello hello = new Hello(); HelloWorld proxy = new HelloWorldDynamicProxy(hello).getProxy(); proxy.say(); } }结果:
Hello Dota Hello World Hello Dota2jdk中的动态代理需要被代理类实现了某个接口。但是cglib可以代理一个没有实现任何接口的类。cglib创建代理的速度比较慢,但是创建代理后运行的速度却非常快,而jdk动态代理却正好相反。还是用上面的例子,cglib的代理类如下。
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibDynamicProxy implements MethodInterceptor { private static CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy(); public static CglibDynamicProxy getInstance(){ return cglibDynamicProxy; } @SuppressWarnings("unchecked") public <T> T getProxy(Class<T> cls){ return (T) Enhancer.create(cls,this); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("dota"); Object object = methodProxy.invokeSuper(o,objects); System.out.println("dota2"); return object; } public static void main(String args[]){ CglibDynamicProxy.getInstance().getProxy(Hello.class).say(); } }另外如果工程用maven管理,使用cglib需要添加maven依赖
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> 相关资源:python入门教程(PDF版)