疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

理解Java三种代理模式


 

 
一、代理模式
 
  代理,顾名思义可以简单理解为代为管理,代理模式就是为其他对象提供额外服务,控制访问(前置处理),或做善后处理(后置处理)。有了代理之后,可以在原来功能的基础上由代理完成另外一部分事情。
 
  常见的代理模式有:
 
静态代理:这种代理模式需要代理对象和目标对象实现相同的接口。可以在不修改目标对象的基础上扩展功能。
缺点:静态代理由于需要和目标对象实现相同的接口,当代理对象变多的时候代理类就会跟着增加,而且一旦更改了接口,那么目标对象和代理对象都要同时做出调整,不方便管理。
动态代理:代理对象不需要实现目标对象接口,通过JAVA的API动态生成目标对象的代理对象。Proxy.newProxyInstance(。。。),其中有三个参数:
ClassLoader loader:目标对象的类加载器
Class<?>[] interfaces:目标对象的接口类型
InvocationHandler h:事件处理函数,实现对目标对象的操作。
CGLIB动态代理:也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展。
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.
Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.
二、静态代理(需要接口)
 
  静态代理需要目标对象和代理对象实现相同的接口:
 
  UserDaoInterface接口类:
 
1 public interface UserDaoInterface {
2     public void save();
3 }
  目标对象:
 
1 public class UserDao implements UserDaoInterface {
2     public void save() {
3         System.out.println("保存用户信息中。。。。");
4     }
5 }
  代理对象:
 
复制代码
 1 /**
 2  * 代理对象,和目标对象实现相同接口
 3  */
 4 public class UserDaoProxy implements UserDaoInterface {
 5     private UserDaoInterface userDao;
 6 
 7     public UserDaoProxy(UserDaoInterface userDao) {
 8         this.userDao = userDao;
 9     }
10 
11     public void save() {
12         System.out.println("开始保存");
13         userDao.save();
14         System.out.println("保存成功");
15     }
16 }
复制代码
  测试类:
 
复制代码
1 public class Test {
2     @org.junit.jupiter.api.Test
3     public void testDemo(){
4         System.out.println("静态代理");
5         //获取对象
6         UserDaoInterface userDao = new UserDaoProxy(new UserDao());
7         userDao.save();
8     }
9 }
复制代码
  实现结果:
 
 
 
  如果要增加接口的方法,目标对象和代理对象类都需要修改。
 
三、动态代理(需要接口)
 
  动态代理,代理对象无需刻意实现目标对象接口。
 
  接口类
 
1 public interface UserDaoInterface {
2     public void save();
3 }
  目标类
 
1 public class UserDao implements UserDaoInterface {
2     public void save() {
3         System.out.println("保存用户信息中。。。。");
4     }
5 }
 
 
  代理类(动态代理,代理类没有实现和目标对象一样的接口 而是通过javaAPI在内存中为我们动态创建了一个代理对象)
 
复制代码
 1 /**
 2  * 代理工厂类
 3  */
 4 public class ProxyFactory {
 5     private Object obj;
 6 
 7     public ProxyFactory(Object obj) {
 8         this.obj = obj;
 9     }
10 
11     public Object getInstance(){
12         return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
13             obj.getClass().getInterfaces(),
14             new InvocationHandler() {
15                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
16                     System.out.println("开始保存");
17                     Object returnObject = method.invoke(obj,args);
18                     System.out.println("保存成功");
19                     return returnObject;
20                 }
21             });
22     }
23 }
复制代码
 
 
  测试类:
 
复制代码
 1 public class Test {
 2     @org.junit.jupiter.api.Test
 3     public void testDemo(){
 4         System.out.println("动态代理");
 5         UserDaoInterface target = new UserDao();
 6         UserDaoInterface proxy =(UserDaoInterface) new ProxyFactory(target).getInstance();
 7         proxy.save();
 8         System.out.println("原生对象:"+target.getClass());
 9         System.out.println("代理对象:"+proxy.getClass());
10     }
11 }
复制代码
  运行结果:
 
 
 
从结果中我们可以看出返回的是一个javaAPI的代理对象。
 
四、CGLIB代理(无需接口)
 
  CGLIB代理不需要目标对象有实现接口,它通过构建目标对象的子类对目标功能进行扩展
 
  目标对象类:
 
1 public class UserDao{
2     public void save(){
3         System.out.println("保存用户信息");
4     }
5 }
 
 
   代理对象类:
 
复制代码
 1 public class CglibProxy implements MethodInterceptor {
 2 
 3     private Object target;
 4 
 5     public CglibProxy(Object target) {
 6         this.target = target;
 7     }
 8 
 9     //给目标对象创建代理对象
10     public Object getProxyInstance(){
11         /**
12          * 1.工具类,允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。
13          * 和Proxy不一样的是,不管是接口还是类他都能正常工作
14          */
15         Enhancer en = new Enhancer();
16         /**
17          * 2.设置父类
18          */
19         en.setSuperclass(target.getClass());
20         /**
21          * 3.设置回掉函数(因为MethodInterceptor继承了Callback类,默认执行intercept方法)
22          */
23         en.setCallback(this);
24         /**
25          * 4.创建子类
26          */
27         return en.create();
28     }
29 
30     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
31         System.out.println("开始保存");
32         Object returnObject = method.invoke(target,objects);
33         System.out.println("保存结束");
34         return returnObject;
35     }
36 }
复制代码
    测 试类:
 
复制代码
1 public class Test {
2     @org.junit.jupiter.api.Test
3     public void testDemo(){
4         System.out.println("cglib代理");
5         UserDao userDao =(UserDao) new CglibProxy(new UserDao()).getProxyInstance();
6         userDao.save();
7     }
8 }
复制代码
 
 
  运行结果: