• 代理模式


    代理提供了对目标对象的另外的访问方式,即通过代理对象访问目标对象,这样可以扩展目标对象的功能。

    java有三种代理模式,分别为静态代理、动态代理、cglib代理

    代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象

    1、静态代理

    静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类

    接口

    public interface IUserDao {

        public void add();
    }

    目标对象

    public class UserDao implements IUserDao {

        @Override
         public void add() {
             System.out.println("添加方法");
         }

    }

    代理对象

    public class UserProxy implements IUserDao{

        private IUserDao userDao;
        
         public UserProxy(IUserDao userDao) {
             super();
             this.userDao = userDao;
         }

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

    }

    测试类

    public static void main(String[] args) {
             User user = new User();
             //目标对象
             UserDao userDao = new UserDao();
             //把目标对象传给代理对象
             UserProxy proxy = new UserProxy(userDao);
             //执行的是代理的方法
             proxy.add();
            
         }

    静态代理优缺点:

    优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展.

    缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护

    要克服静态代理的缺点就需要用到动态代理


    2、动态代理

    接口和实现类同上静态代理

    动态代理需要增加一个代理工厂ProxyFactory

    public class ProxyFactory {
        
         private Object target;

        public ProxyFactory(Object target) {
             super();
             this.target = target;
         }
        
         public Object getProxyInstance() {
             return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
                
                 @Override
                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                     //可以扩展方法
                     System.out.println("开始事务");
                     //执行目标对象方法
                     Object invoke = method.invoke(target, args);
                     System.out.println("提交事务");
                     return invoke;
                 }
             });
                    
         }
    }

    测试类

    public static void main(String[] args) {
         UserDao userDao = new UserDao();
         //给目标对象生成代理对象,注意此处用的是接口而不是实现类,否则会报转换错误
         IUserDao proxy =(IUserDao) new ProxyFactory(userDao).getProxyInstance();
        
         User user = new User();
        
         //代理对象执行方法
         proxy.add();
        
    }

    动态代理中,代理类并不是在Java代码中实现,而是在运行时期生成,相比静态代理,动态代理可以很方便的对委托类的方法进行统一处理,如添加方法调用次数、添加日志功能等等


    3、cglib代理

    cglib代理也叫子类代理,静态代理和动态代理都需要目标对象实现一个接口,但是实际情况可能是目标函数没有实现接口,此时就可以用cglib代理,它可以在内存中构建一个子类对象来对目标对象的函数来进行扩展

    目标对象

    public class CglibDao {

        public void save() {
             System.out.println("执行保存方法");
         }
    }

    创建一个代理工厂,需要引入一个cglib的依赖

    <dependency>
                 <groupId>cglib</groupId>
                 <artifactId>cglib</artifactId>
                 <version>3.2.6</version>
             </dependency>

    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 ProxyFactory2 implements MethodInterceptor{

        private Object target;
        
         public ProxyFactory2(Object target) {
             super();
             this.target = target;
         }
         public Object getProxyInstance(){
             //工具类
             Enhancer en = new Enhancer();
             //设置父类
             en.setSuperclass(target.getClass());
             //设置回调函数
             en.setCallback(this);
             //创建子类(代理对象)
             return en.create();
         }
         @Override
         public Object intercept(Object obj, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
            
             System.out.println("开始事务");
             //执行目标类方法,此处的的invoke的第一个参数为target而不是代理对象obj,否则会不断递归调用intercept方法而导致内存溢出
             Object invoke = method.invoke(target, arg2);
             System.out.println("提交事务");
             return invoke;
         }
    }


    测试类

    public static void main(String[] args) {
         CglibDao cglibDao = new CglibDao();
         //给目标对象生成代理对象
         CglibDao proxy =(CglibDao) new ProxyFactory2(cglibDao).getProxyInstance();
         //代理对象执行方法
         proxy.save();
    }

    cglib也有局限,它也跳不出jdk的继承机制,对final类无能为力

  • 相关阅读:
    GNN layer Learner
    邻接矩阵转稀疏矩阵 Learner
    PyTorch查看模型和数据是否在GPU上 Learner
    论文解读(GraphCL)《Graph Contrastive Learning with Augmentations》 Learner
    矩阵的迹及迹的求导 Learner
    论文解读《Cauchy Graph Embedding》 Learner
    torch.spmm矩阵乘法 Learner
    ERROR: No matching distribution found for torch==1.2.0 解决方法 Learner
    拉普拉斯特征映射(Laplacian Eigenmaps) Learner
    JWT的介绍与项目使用
  • 原文地址:https://www.cnblogs.com/liaopeng/p/8405112.html
Copyright © 2020-2023  润新知