zoukankan      html  css  js  c++  java
  • SpringAOP--代理

    前言

      在Spring或者SpringBoot中,可以通过@Aspect注解和切点表达式等配置切面,实现对某一功能的织入。然而其内部到底是如何实现的呢?

      实际上,Spring在启动时为切点方法所在类生成了代理类,通过操作代理类代替操作实际类,从而实现在真正调用方法之前或之后,插入一些我们自定义的逻辑。

      如何生成代理类呢?

         

    JDK动态代理

    • JDK动态代理要求 被代理类必须有接口抽象。
    • 通过实现  InvocationHandler 接口并实现  invoke(Object proxy, Method method, Object[] args) 方法进行自定义逻辑的织入:
      • proxy :当前的代理类实例;
      • method:被代理的方法;
      • args:方法入参;

    invoke方法的官方说明如下:即在

    * Processes a method invocation on a proxy instance and returns
    * the result. This method will be invoked on an invocation handler
    * when a method is invoked on a proxy instance that it is
    * associated with. 

      使用示例:

    1、被代理的方法:

    // 方法实现
    public class HelloAOPImpl implements HelloAOP {
        @Override
        public String sayHello() {
            String hello = "你好,AOP";
            System.out.println(hello);
            return hello;
        }
    }
    View Code

      

    2、配置自定义调用处理器

    public class MyInvocationHandler implements InvocationHandler {
        private Object target;
      // 通过构造函数将配代理对象注入
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
    
        //回调
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("我是代理,有人让我对你说:");
            /**调用前,自定义业务*/
            Object res = method.invoke(target, args);
            /**调用后,自定义业务*/
            return res;
        }
        //获取代理类实例
        public <T> T getProxyInstance(){
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
    }

          2:调用与输出:

    public static void main(String[] args) {
            HelloAOPImpl helloAOP = new HelloAOPImpl();
            MyInvocationHandler myInvocationHandler = new MyInvocationHandler(helloAOP);
            HelloAOP proxy = myInvocationHandler.getProxyInstance();
            proxy.sayHello();
     }
    
    // 输出
    我是代理,有人让我对你说:
    你好,AOP
    View Code 

    一个疑问:代理类如何取代被代理类的呢?

    CGLIB动态代理

     CGLIB动态代理不需要代理对象实现某个接口:

    1、被代理类(没有接口实现)

    public class HelloAOPImpl2 {
        public void sayHello() {
            String s = "你好,AOP";
            System.out.println(s);
        }
    }
    View Code

    2、CGLIB代理

    public class CgibAOP2 implements MethodInterceptor {
        private Object target;
    
        /**
         * 通过构造函数设置被代理对象
         * @param target
         */
        public CgibAOP2(Object target) {
            this.target = target;
        }
    
        /**
         * 回调该方法。
         * @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("say之前:"+ method+"1");
            Object res = method.invoke(target, objects);
            System.out.println("say之后:"+ method+"1");
            return res;
        }
    
        /**
         * 生成代理实例
         * @return
         */
        public Object getProxy(){
            // 通过增强实现
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(this); //设置回调
            Object res = enhancer.create();
            return res;
        }
    }

    3、测试:

    public class Test {
        public static void main(String[] args) {
            HelloAOPImpl2 helloAOP = new HelloAOPImpl2();
            HelloAOPImpl2 proxy =  (HelloAOPImpl2)new CgibAOP2(helloAOP).getProxy();
            proxy.sayHello();
        }
    }
    View Code

    输出:

    say之前:public void com.wht.springaop.DynamicProxy.Cglib.HelloAOPImpl2.sayHello()1
    你好,AOP
    say之后:public void com.wht.springaop.DynamicProxy.Cglib.HelloAOPImpl2.sayHello()1
    View Code
  • 相关阅读:
    不是结束,而是刚刚开始
    第七次作业
    用类做封装
    用户故事
    团队编程--MP3播放器
    结对编程作业
    四则运算
    四、小电视自动抽奖
    三、wss连接B站弹幕
    一、基础设计
  • 原文地址:https://www.cnblogs.com/whtblog/p/11443217.html
Copyright © 2011-2022 走看看