动态代理这个名词就不用多说了,是经典的二十三种设计模式中的一种。代理模式也不多说,现在聊聊动态代理的方式。
第一种方式是JDK自带方式,原理是在程序运行时,运用反射机制动态创建而成,不过它有一个先决条件就是被代理对象必须是实现某个接口的对象才能代理。看代码:
public interface Book {
public void addBook();
}
好简答的一个接口,接下来是实现接口第一个类:
public class Bookimpl implements Book{ @Override public void addBook() { System.out.println("do addBook~~~"); } }
也是最普通不过的一个类了!接下来是实现动态代理的类
public class DynamicProxyHandler implements InvocationHandler{ private Object proxid; public DynamicProxyHandler(){} public DynamicProxyHandler(Object porxid){ this.proxid = porxid; } @Override public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable { System.out.println("before===="); // TODO Auto-generated method stub method.invoke(proxid, arg); System.out.println("after===="); return null; } public Object bind(Object proxid){ this.proxid = proxid; return Proxy.newProxyInstance(proxid.getClass().getClassLoader(), proxid.getClass().getInterfaces(), this); } public static void main(String[] args) { DynamicProxyHandler dph = new DynamicProxyHandler(); Book bmp = (Book)dph.bind(new Bookimpl()); bmp.addBook(); } }
实现 InvocationHandler 接口的一个类 主要实现的是invoke方法,改方法有三个参数,分别是:
proxy:被代理对象
method:被代理方法
arg:被代理方法参数
注意invoke方法里面的method.invoke方法的参数,第一个参数是被代理对象,但不是proxy是proxid,prixid是被代理对象,对于本例子就是new Bookimpl()
第二个要讲的方法是:Proxy.newProxyInstance 该方法有三个参数,第一个是ClassLoader,第二个是被代理对象接口方法,第三个是实现了InvocationHandler的实例。它的返回值就是被代理对象 如:
Book bmp = (Book)dph.bind(new Bookimpl());
然后直接调用要代理的方法addBook就行!
第二种代理方式是Cglib动态代理 :
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。请看代码:
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class BookCglib implements MethodInterceptor { private Object target; /** * 创建代理对象 * * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } @Override // 回调方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("before"); proxy.invokeSuper(obj, args); System.out.println("after"); return null; } }
调用是这样的:
public class TestCglib { public static void main(String[] args) { BookCglib cglib=new BookFacadeCglib(); BookFimpl bookCglib= (Bookimpl)cglib.getInstance(cglib); bookCglib.addBook(); } }