jdk(只针对有接口的)

 1 public class JdkProxy implements InvocationHandler {
 2 
 3     private Object real;
 4 
 5     private Class interfaceClass;
 6 
 7     public JdkProxy(Object real, Class interfaceClass) throws Exception {
 8         if(real==null&&interfaceClass==null){
 9             throw new Exception("不允许同时为空!");
10         }
11         if(real!=null){
12             this.real = real;
13         } else {
14             this.interfaceClass = interfaceClass;
15         }
16     }
17 
18     //所有方法的增强操作
19     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
20         //System.out.println("内存代理类proxy"+proxy);//出现java.lang.StackOverflowError栈深度溢出,会调proxy.toString()方法
21         System.out.println("invoke start:"+method.getName());
22         Object result;
23         if(real!=null){
24             result = method.invoke(real, args);
25         } else {
26             //只传过来一个接口,这个地方的逻辑想怎么写都行的
27             result = "不代理具体的对象,只要实现接口就行了,这里写实现接口的方法";
28         }
29         System.out.println("invoke end:"+method.getName());
30         return result;
31     }
32 
33     //定义获取代理对象方法
34     public Object getJDKProxy(){
35         if(real!=null){
36             return Proxy.newProxyInstance(real.getClass().getClassLoader(), real.getClass().getInterfaces(), this);
37         } else {
38             return Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, this);
39         }
40     }
41 
42     /**
43      * 保存class文件
44      * @param clazz class对象
45      * @param proxyName 代理类的名字,可随意指定
46      */
47     public void saveClassFile(Class clazz,String proxyName) {
48         //生成class的字节数组,此处生成的class与proxy.newProxyInstance中生成的class除了代理类的名字不同,其它内容完全一致
49         byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces());
50         FileOutputStream fos = null;
51         try {
52             fos = new FileOutputStream("C:\\class\\" + proxyName + ".class");
53             fos.write(classFile);//保存到磁盘
54             fos.flush();
55         }catch(Exception e) {
56             e.printStackTrace();
57         }finally {
58             try {
59                 fos.close();
60             }catch(IOException e) {
61                 e.printStackTrace();
62             }
63         }
64     }
65 
66     interface UserService {
67         void doSomething();
68     }
69 
70     static final class UserServiceImpl implements UserService {
71         public final void doSomething() {
72             System.out.println("真实对象的方法执行过程...");
73         }
74     }
75 
76     public static void main(String[] args) throws Exception {
77         //System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //设置系统属性
78         //JdkProxy jdkProxy = new JdkProxy(new UserServiceImpl(), null);
79         JdkProxy jdkProxy = new JdkProxy(null, UserService.class);
80         Object proxy = jdkProxy.getJDKProxy();
81         ((UserService)proxy).doSomething();
82         jdkProxy.saveClassFile(proxy.getClass(), "proxyName");
83     }
84 }
JdkProxy
核心原理:

1.在内存中生成新对象,新对象中持有invocationHandler对象,实现了原接口,继承父类Proxy

2.新内存对象实现原接口的方法,内部直接调用invocationHandler.invoke()方法,因为invocationHandler中持有原接口的真实对象,相当于间接调用了真实对象

3.重写了equals、hashCode、toString

4.注意如果在invocationHandler.invoke()方法中要用代理类proxy来调用任何方法,都会出现递归循环调用,出现java.lang.StackOverflowError栈深度溢出

 5.可以没有真实对象,只有接口类,在内存中生成实现接口的对象,依赖invocationHandler对象来自定义接口方法的具体实现;mybatis中,根据接口mapper,生成mapper对象就是利用这个功能

 

cglib(针对没有接口的),原有类不能有父类,非final修饰的类和方法

 1 public class CglibProxy implements MethodInterceptor {
 2 
 3     private Class clazz;
 4 
 5     private boolean isInterface;
 6 
 7     public CglibProxy(Class clazz){
 8         isInterface = clazz.isInterface();
 9         this.clazz = clazz;
10     }
11 
12     //所有方法的增强拦截操作
13     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
14         //System.out.println("内存代理类obj"+obj);//出现java.lang.StackOverflowError栈深度溢出
15         System.out.println("Cglib动态代理,监听开始:"+method.getName());
16         Object result;
17         if(!isInterface){
18             result = proxy.invokeSuper(obj, args);//调用父类的方法执行
19         } else {
20             //只传过来一个接口,这个地方的逻辑想怎么写都行的
21             result = "只要实现接口就行了,这里写实现接口的方法";
22         }
23         System.out.println("Cglib动态代理,监听结束:"+method.getName());
24         return result;
25     }
26 
27     //定义获取代理对象方法
28     public Object getCglibProxy(){
29         //为目标对象target赋值
30         Enhancer enhancer = new Enhancer();
31         //设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
32         enhancer.setSuperclass(clazz);
33         enhancer.setCallback(this);// 设置回调
34         /*enhancer.setCallbackFilter(new CallbackFilter() {
35             public int accept(Method method) {
36                 return 0;
37             }
38         });
39         enhancer.setCallback(new LazyLoader() {
40             public Object loadObject() throws Exception {
41                 return null;
42             }
43         });
44         enhancer.setCallback(new Dispatcher() {
45         public Object loadObject() throws Exception {
46             return null;
47             }
48         });
49         enhancer.setCallback(new ProxyRefDispatcher() {
50             public Object loadObject(Object o) throws Exception {
51                 return null;
52             }
53         });
54         enhancer.setCallback(new FixedValue() {
55             public Object loadObject() throws Exception {
56                 return "FixedValue";
57             }
58         });
59         enhancer.setCallback(NoOp.INSTANCE);//NoOp回调把对方法调用直接委派到这个方法在父类中的实现(也可以理解成真实对象直接调用方法);
60         Callback callbacks[] = new Callback[] {this, NoOp.INSTANCE};
61         enhancer.setCallbacks(callbacks);*/
62         //setCallbacks配合CallbackFilter一起使用
63         enhancer.setCallbackFilter(new CallbackFilter() {
64             public int accept(Method method) {
65                 return 0;
66             }
67         });
68         Object result = enhancer.create();//创建并返回代理对象
69         return result;
70     }
71 
72     interface UserService {
73         void doSomething();
74     }
75 
76     static class UserServiceImpl implements UserService{
77         public void doSomething() {
78             System.out.println("真实类的方法执行过程...");
79         }
80     }
81 
82     public static void main(String[] args) {
83         System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\class");
84         //CglibProxy cglibProxy = new CglibProxy(UserServiceImpl.class);
85         CglibProxy cglibProxy = new CglibProxy(UserService.class);
86         Object proxy = cglibProxy.getCglibProxy();
87         ((UserService)proxy).doSomething();
88     }
89 }
CglibProxy

核心原理:

1.根据原有类,内存中生成其子类,重写所有方法

2.因为增加了一个callback接口,在Enhancer生成子类的时候,更加灵活,可以多个setCallbacks配合setCallbackFilter,不同的callback可以实现不同的增强功能

3.原有类可以是一个接口,依靠MethodInterceptor对象生成具体接口方法的实现,mybatis中,根据接口mapper,生成mapper对象也可以利用这个实现