java 的三种代理模式

(一)https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247485265&idx=1&sn=0ea1fe4257cb963d24829f69bb6a32da&chksm=ebd6387ddca1b16b87f12f50b24b239bed93e0e49f243ec560e2c83156ff5ceefe0a2b2e96fc&mpshare=1&scene=1&srcid=0427wPQP4tYUBtlGH5l1JR9i&key=c44bed40495664a4adac9e43d1f05551d8a4f754cb59ce155cd03562861b122f33144ac9d8403e70841b6302eb1f140b592c78f18e0454b0ee34a2ca8276efd12dbd8e67c6c51b455a6ebd0250532b8e&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=zTFOqug6RXGHRQVhLFV5xM2VvZe0nSmsXV1%2Fys3HrXZVPSKfgf3TVZ7FuYVWc0LA



1. 静态代理

public class UserDaoProxy implements IUserDao {

    private IUserDao target;
    public UserDaoProxy(IUserDao target){
        this.target = target;
    }

    @Override
    public void save() {
        System.out.println("开始事务static");
        target.save();//执行目标对象的方法
        System.out.println("提交事务static");
    }
}


2. 动态代理

public class ProxyFactory implements InvocationHandler {
    //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始事务jdk");
        Object returnValue = method.invoke(target, args);
        System.out.println("提交事务jdk");
        return returnValue;
    }

    //给目标对象生成代理对象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

}


一个被代理对象,一个invoke改写埋点,一个创建代理对象


        // 目标对象
        IUserDao target = new UserDao();

        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();

        // 执行方法   【代理对象】
        proxy.save();

    }


3. cglib

public class ProxyFactory implements MethodInterceptor {
    //维护目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();

    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始事务cglib");

        //执行目标对象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事务cglib");

        return returnValue;
    }
}
与jdk相同,

一个被代理对象,一个invoke改写埋点,一个创建代理对象



        //目标对象
        UserDao target = new UserDao();

        //代理对象
        UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();

        //执行代理对象的方法
        proxy.save();



(二)https://blog.csdn.net/tanga842428/article/details/52716875

Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP 

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

如何强制使用CGLIB实现AOP?
 (1)添加CGLIB库,SPRING_HOME/cglib/*.jar
 (2)在spring配置文件中加入
<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK动态代理和CGLIB字节码生成的区别?
 (1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
 (2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
   因为是继承,所以该类或方法最好不要声明成final 



JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,它有几个要求
* 实现InvocationHandler 
* 使用Proxy.newProxyInstance产生代理对象
* 被代理的对象必须要实现接口

使用JDK动态代理,目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。


CGLib 必须依赖于CGLib的类库,
Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型针对接口编程的环境下推荐使用JDK的代理。从执行效率上看,Cglib动态代理效率较高。在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行


个人总结:

jdk方式,实现InvocationHandler接口,使用Proxy,基于反射、动态编译 为实现某接口的类创建代理类

cglib方式,基于字节码,生成子类改写方法,方法不能为final



此外有一个2层jdk动态代理例子:

http://www.cnblogs.com/jiangyi-uestc/p/5755133.html


JDK的代理方式主要就是通过反射跟动态编译来实现的,主要搭配InvocationHandler和Proxy来实现,下面的例子中使用了两层代理(即代理上加了一层代理)。

 

二、实例

1. 公共接口

复制代码
1 package com.tgb.proxy;
2 
3 public interface UserMgr {
4 
5     void addUser();
6     void delUser();
7     
8 }
复制代码

 

2. 实现类

复制代码
 1 package com.tgb.proxy;
 2 
 3 public class UserMgrImpl implements UserMgr {
 4 
 5     @Override
 6     public void addUser() {
 7         System.out.println("添加用户....");
 8     }
 9 
10     @Override
11     public void delUser() {
12         System.out.println("删除用户.....");
13     }
14 
15 }
复制代码

 

3. TransactionHandler(InvocationHandler的实现)

复制代码
 1 package com.tgb.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class TransactionHandler implements InvocationHandler {
 7 
 8     private Object target;
 9     
10     public TransactionHandler(Object target){
11         super();
12         this.target = target;
13     }
14 
15     @Override
16     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
17         
18         System.out.println("开启事务...");
19         
20         method.invoke(target);
21         
22         System.out.println("提交事务...");
23         
24         return null;
25     }
26     
27 
28 }
复制代码

 

4. TimeHandler(InvocationHandler的实现)

复制代码
 1 package com.tgb.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.util.Calendar;
 6 
 7 public class TimeHandler implements InvocationHandler {
 8 
 9     private Object target;
10 
11     public TimeHandler(Object target) {
12         super();
13         this.target = target;
14     }
15 
16     @Override
17     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
18 
19         Calendar calendar = Calendar.getInstance();
20 
21         System.out.println("start time:" + calendar.get(Calendar.HOUR_OF_DAY));
22 
23         method.invoke(target);
24 
25         System.out.println("end time:" + calendar.get(Calendar.HOUR_OF_DAY));
26 
27         return null;
28     }
29 
30 }
复制代码

 

5. 测试类

复制代码
 1 package com.tgb.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Proxy;
 5 
 6 public class Client {
 7 
 8     public static void main(String[] args) {
 9 
10         UserMgr userMgr = new UserMgrImpl();
11 
12         // 1.第一层代理----------通过动态代理,添加事务处理
13         InvocationHandler handler = new TransactionHandler(userMgr);
14         UserMgr userMgrProxy = (UserMgr) Proxy.newProxyInstance(userMgr.getClass().getClassLoader(),
15                 userMgr.getClass().getInterfaces(), handler);
16 
17         // 2.第二层代理----------通过动态代理,添加时间处理
18         InvocationHandler handler2 = new TimeHandler(userMgrProxy);
19         UserMgr userMgrProxy2 = (UserMgr) Proxy.newProxyInstance(userMgrProxy.getClass().getClassLoader(),
20                 userMgrProxy.getClass().getInterfaces(), handler2);
21 
22         userMgrProxy2.addUser();
23 
24         System.out.println("========================================");
25 
26         userMgrProxy2.delUser();
27 
28     }
29 }
复制代码

 

输出结果:

复制代码
start time:Tue Aug 09 23:54:54 CST 2016
开启事务...
添加用户....
提交事务...
end time:Tue Aug 09 23:54:54 CST 2016
========================================
start time:Tue Aug 09 23:54:54 CST 2016
开启事务...
删除用户.....
提交事务...
end time:Tue Aug 09 23:54:54 CST 2016
复制代码

posted on 2018-04-29 23:54  silyvin  阅读(411)  评论(0编辑  收藏  举报