最简单的是静态代理方法,即代理模式,这里就不多啰嗦了。。
重点说一下JDK的动态代理和Cglib的动态代理吧
先说JDK的,需要被代理的类需要有接口,否则无法实现
1package proxy.dynamic; 2 3public interface IBook { 4 void add(); 5} 6
实现接口的类如下
1package proxy.dynamic; 2 3public class Book implements IBook { 4 5 @Override 6 public void add() { 7 System.out.println("Add Method!"); 8 } 9 10 11 12}
创建一个代理类,需要实现一个接口InvocationHandler接口,里面有一个invoke方法需要实现
同时创建一个生成实例的方法
1package proxy.dynamic; 2 3import java.lang.reflect.InvocationHandler; 4import java.lang.reflect.Method; 5import java.lang.reflect.Proxy; 6 7public class BookProxy implements InvocationHandler{ 8 private Object target; 9 10 public Object bind(Object target) { 11 this.target = target; 12 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);//这里需要接口 13 } 14 @Override 15 public Object invoke(Object proxy, Method method, Object[] args) 16 throws Throwable { 17 Object result=null; 18 System.out.println("Before"); 19 result=method.invoke(target, args);//执行方法 20 System.out.println("After"); 21 return result; 22 } 23 24 25 26 27}
接下来创建测试类
1package proxy.dynamic; 2 3public class Test { 4 5 /** 6 * @param args 7 */ 8 public static void main(String[] args) { 9 BookProxy bp = new BookProxy(); 10 IBook book = (IBook) bp.bind(new Book()); 11 book.add(); 12 13 } 14 15}
可以看到依次输出了Before,方法,After
下面说一下Cglib的代理,Cglib代理不需要原类实现接口,依赖Cglib和asm两个Jar包
需要代理的类如下
1package cglib.proxy; 2 3public class Book { 4 5 public void add() { 6 System.out.println("Add Method!"); 7 } 8}
创建一个代理类,实现MethodInterceptor接口,同时写一个生成实例的getInstance方法
1package cglib.proxy; 2 3import java.lang.reflect.Method; 4 5import net.sf.cglib.proxy.Enhancer; 6import net.sf.cglib.proxy.MethodInterceptor; 7import net.sf.cglib.proxy.MethodProxy; 8 9public class CglibProxy implements MethodInterceptor{ 10 private Object target; 11 public Object getInstance(Object target){ 12 this.target=target; 13 Enhancer enhancer = new Enhancer(); 14 enhancer.setSuperclass(this.target.getClass()); 15 enhancer.setCallback(this); 16 return enhancer.create(); 17 } 18 @Override 19 public Object intercept(Object obj, Method method, Object[] args, 20 MethodProxy proxy) throws Throwable { 21 22 System.out.println("Before"); 23 proxy.invokeSuper(obj, args); 24 System.out.println("After"); 25 return null; 26 } 27 28 29 30}
接下来就是简单测试一下
1package cglib.proxy; 2 3public class Test { 4 5 /** 6 * @param args 7 */ 8 public static void main(String[] args) { 9 CglibProxy proxy = new CglibProxy(); 10 Book book=(Book) proxy.getInstance(new Book()); 11 book.add(); 12 13 } 14 15}
运行效果一样的
简单总结一下,JDK动态代理,需要实现一个接口InvocationHandler,要求被代理的对象必须有一个接口
Cglib代理需要实现MethodInterceptor接口,不需要被代理的类必须有接口
性能方法,参考其他文章,说JDK代理适合多例模式,而单例模式Cglib更好一些,因为Cglib是用底层的字节码技术生成实例,耗费时间较长,性能不如JDK动态代理。(有待验证。。)