一:JDK动态代理
1.创建接口
1 2 3 4 5
| public interface Subject { public void rent();
public void hello(String str); }
|
2.创建接口实现类
1 2 3 4 5 6 7 8 9 10
| public class RealSubject implements Subject {
public void rent() { System.out.println("I want to rent my house"); }
public void hello(String str) { System.out.println("hello: " + str); } }
|
3.创建动态代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class DynamicProxy implements InvocationHandler {
private Object subject;
public DynamicProxy(Object subject) { this.subject = subject; }
public Object invoke(Object object, Method method, Object[] args) throws Throwable { System.out.println("before rent house");
System.out.println("Method:" + method);
method.invoke(subject, args);
System.out.println("after rent house");
return null; }
}
|
4.创建客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class Client {
public static void main(String[] args) { Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxy(realSubject);
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject .getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
}
|
代理接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public interface IHello { String say(String aa); }
public class FacadeProxy implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("接口方法调用开始"); System.out.println("method toGenericString:"+method.toGenericString()); System.out.println("method name:"+method.getName()); System.out.println("method args:"+(String)args[0]); System.out.println("接口方法调用结束"); return "调用返回值"; } public static <T> T newMapperProxy(Class<T> mapperInterface) { ClassLoader classLoader = mapperInterface.getClassLoader(); Class<?>[] interfaces = new Class[]{mapperInterface}; FacadeProxy proxy = new FacadeProxy(); return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); } }
public class Test { public static void main(String[] args) { IHello hello = FacadeProxy.newMapperProxy(IHello.class); System.out.println(hello.say("hello world")); } }
|
二:CLIiB动态代理
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
1.创建对象
这是一个需要被代理的类,也就是父类,通过字节码技术创建这个类的子类,实现动态代理。
1 2 3 4 5
| public class SayHello { public void say(){ System.out.println("hello everyone"); } }
|
2.创建动态代理类
该类实现了创建子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,proxy为代理类实例。proxy.invokeSuper(obj, args)通过代理类调用父类中的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); }
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result; } }
|
3.客户端
1 2 3 4 5 6 7 8
| public class DoCGLib { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class); proxyImp.say(); } }
|
三:对比
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。