1. 静态代理
- 接口A;
- 实现a1,实现A中的方法;
- 代理a2,
(AProxy implement A
),成员中有a1,这样实际干活的是a1,但是a2可以夹带一些私货,比如打上日志什么的。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class AProxy implements AInterface { private A1 a1; public AProxy(A1 a1) { this.a1 = a1; } public void doSomething() { System.out.println("代理类方法,进行了增强。。。"); System.out.println("事务开始。。。"); a1.doSomething(); System.out.println("处理结束。。。"); } }
|
2. jdk动态代理
上述静态代理的特点是,如果有n个接口要代理,那么相应的静态代理a2也会有很多。
动态代理的方法就是用反射来动态生成一个代理。而不用每次写非常相似的代码。
- 接口A;
- 实现a1,实现A中的方法;
- 动态代理,传入a1,通过反射创建一个与a1接口一样的类A2,并生成一个对象a2。
然后定义每次invoke的时候需要夹带的私货(打日志)。
外界使用的时候,比静态代理多一步。
静态代理: 1.传入a1,得到一个代理a2.
动态代理: 2.传入a1,得到一个handler,再从handler中获取代理a2.(getProxy)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class DynamicProxyTest { private static class AHandler implements InvocationHandler {
private Object a1Impl;
public AHandler(Object a1Impl) { super(); this.a1Impl = a1Impl; }
public Object getProxy() throws Throwable { return Proxy.newProxyInstance(Thread.currentThread() .getContextClassLoader(), this.a1Impl.getClass() .getInterfaces(), this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result; System.out.println("代理类方法,进行了增强。。。"); System.out.println("事务开始。。。"); result = method.invoke(a1Impl, args); System.out.println("事务结束。。。"); return result; } }
public static void main(String[] args) throws Throwable { A a1 = new A1(); AHandler handler = new AHandler(a1); A a2 = (A) handler.getProxy(); a2.doSomething(); }
}
|
3. cglib动态代理
上述jdk的静态代理和动态代理,本质上都是用接口指针存放实现的对象,然后偷偷用包装了a1的代理a2,替换指针里的对象。
初始化时,代理a2的接口声明和a1一样即可。
因此jdk的静态代理和动态代理都要求被代理的实现对象声明实现了某一个接口。
cglib代理则不同,用的是基类指针存放子类对象,因此并不要求一定要声明实现某一个接口,但必须要是一个可以被继承的类。对于java来说,也就是不能是final类。
jdk代理: 接口引用存放代理对象; 要求实现某接口.
cglib代理: 原类的引用存放代理对象; 要求不是final,可以继承。
具体cglib代理的写法:
1 2 3 4 5
| <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> </dependency>
|
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public class AImpl {
public void doSomething() { System.out.println("AImpl doSomething"); } }
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;
public class AInterceptor implements MethodInterceptor { private Object target;
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("事务开始。。。"); Object result = proxy.invokeSuper(obj, args); System.out.println("事务结束。。。"); return result; }
public static void main(String[] args) { AInterceptor aInterceptor = new AInterceptor(); AImpl a1 = (AImpl) aInterceptor.getInstance(new AImpl()); a1.doSomething(); }
}
|
与jdk动态代理很相似,只是概念术语换一下:
创建一个方法拦截器,传入实现a1,获取一个代理a2。