zoukankan      html  css  js  c++  java
  • 代理

    一、静态代理

      1.创建Subject业务接口

    /**
     * 抽象主题:真实业务接口
     */
    public interface Subject {
        public void doSomething();
    }

      2.创建RealSubject实现Subject接口

     
    /**
     * 真是主题:将业务代码封装到此主题中
     */
    public class RealSubject implements Subject{
        @Override
        public void doSomething() {
            System.out.println("真实业务");
        }
    }
     

      3.创建代理类

     
    /*
    * 代理主题:代理类  生成真实主题对象,调用真是主题的方法
    * 程序就不用直接去创建真是主题了,直接调用代理对象
    *
    *
    * 静态代理:说白了,就是创建一个给程序调用的类(代理类),然后用代理类去调用原始对象
    * */
    public class ProxySubject implements Subject{
        //真实对象
        Subject subject=new RealSubject();
        @Override
        public void doSomething() {
            System.out.println("===========前置增强===========");
            subject.doSomething();
            System.out.println("===========后置增强===========");
        }
    }
     

      3.创建测试类

    public static void main(String[] args) {
    
            ProxySubject  proxySubject=new ProxySubject();
            proxySubject.doSomething();
    }

    二、JDK动态代理 

      1.创建业务接口

     
    /**
    
    * 抽象主题:真实业务接口 */ public interface Subject { public void doSomething(); }
     

      2.创建接口实现类 

    public class RealSubject implements Subject{
        @Override
        public void doSomething() {
            System.out.println("真实业务");
        }
    }

      3.调用管理接口InvocationHandler 创建动态代理类

     
    public static void main(String[] args) {
            //JDK动态代理:要求必须又抽象主题
            //代表的是代理对象 指定对象的原始类型
    
            /*
             * ClassLoading   loader,类加载器:应该是代理对象的类加载器
             * Class<?>[] interfaces,  接口:原始对象实现 接口类型
             * InvocationHandler  h
             * */
            //创建一个原始对象
            final Subject subject = new RealSubject();
            Subject subjetProxy = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("前置增强");
                    Object invoke = method.invoke(subject, args);
                    System.out.println("后置增强");
                    return invoke;
                }
            });
            subjetProxy.doSomething();
    
        }
     

     

    三、cglib动态代理 

      1.创建业务类

    public class   IService {
       public void doSomething(){
           System.out.println("真实业务");
       }
    }

      2.创建代理工厂Bean

     
     public static void main(String[] args) {
            //步骤一:目标对象
            final IService iService=new IService();
            //步骤二:通过cglib提供的nhancer类 生成代理
            Enhancer enhancer=new Enhancer();
            //步骤三 :指定需要代理的目标对象模板(将目标对象放入到代理工厂当中,生成代理对象)
            enhancer.setSuperclass(iService.getClass());
            //步骤四:实现增强的处理操作
            enhancer.setCallback(new MethodInterceptor() {
                /**
                 *
                 * @param o             目标对象
                 * @param method        目标对象的方法
                 * @param objects       目标对象方法的参数
                 * @param methodProxy   代理目标对象方法
                 * @return
                 * @throws Throwable
                 */
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println("前置");
                    Object invoke = methodProxy.invoke(iService, objects);
                    System.out.println("后置");
                    return invoke;
                }
            });
            //最后一步 :创建代理
            IService iServiceproxy = (IService) enhancer.create();
            iServiceproxy.doSomething();
        }
     

    四 、总结

      JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;

      CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;

      如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

      如果目标对象实现了接口,可以强制使用CGLIB实现AOP

      [aop:config proxy-target-class="true"] 强制切换成CGLIB动态代理

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

  • 相关阅读:
    jQuery,from标签,歪路子小技巧
    UniApp随笔
    JS的一些操作
    文本环绕
    Dictionary 存储函数,方法
    GIT项目管理
    Vue2 学习记录
    VSCode + Vue 学习笔记
    Mysql,Insert,Select时自增长问题
    ASP.NET SignalR Troubeshooting
  • 原文地址:https://www.cnblogs.com/danxun/p/11753844.html
Copyright © 2011-2022 走看看