Spring 高级 Spring选择代理 jdk 和 cglib的统一 aspect 和 advisor的区别

一 aspect 和 advisor的区别

 

二 advisor 演示 Spring 选择代理 

package com.mangoubiubiu.show.a15;


import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

import java.lang.reflect.Method;

public class A15 {


    public static void main(String[] args) {

        //1. 备好切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

        pointcut.setExpression("execution(* foo())");

        //2. 备好通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before....");
            Object result = invocation.proceed();
            System.out.println("after....");
            return result;
        };

        //3. 备好切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,advice);

        /**
         * 创建代理
         */
        Target1 target = new Target1();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target);
        factory.addAdvisor(advisor);
        I1 proxy = (I1)factory.getProxy();

        proxy.foo();
        proxy.bar();


    }
    interface I1 {
        void foo();

        void bar();
    }

    static class Target1 implements I1 {
        public void foo() {
            System.out.println("target1 foo");
        }

        public void bar() {
            System.out.println("target1 bar");
        }
    }

    static class Target2 {
        public void foo() {
            System.out.println("target2 foo");
        }

        public void bar() {
            System.out.println("target2 bar");
        }
    }
}

发现 foo方法被增强了

三 Spring创建代理时 是用的哪种实现类

收获💡

  1. 底层的切点实现
  2. 底层的通知实现
  3. 底层的切面实现
  4. ProxyFactory 用来创建代理
    • 如果指定了接口,且 proxyTargetClass = false,使用 JdkDynamicAopProxy
    • 如果没有指定接口,或者 proxyTargetClass = true,使用 ObjenesisCglibAopProxy
    • 例外:如果目标是接口类型或已经是 Jdk 代理,使用 JdkDynamicAopProxy

注意

  • 要区分本章节提到的 MethodInterceptor,它与之前 cglib 中用的的 MethodInterceptor 是不同的接口
package com.mangoubiubiu.show.a15;


import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

import java.lang.reflect.Method;

public class A15 {


    public static void main(String[] args) {

        //1. 备好切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

        pointcut.setExpression("execution(* foo())");

        //2. 备好通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before....");
            Object result = invocation.proceed();
            System.out.println("after....");
            return result;
        };

        //3. 备好切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,advice);

        /**
         * 4 创建代理
         *    a proxyTargetClass = false 目标实现了接口 , 用jdk实现
         *    b proxyTargetClass = false 目标没有实现接口  , 用cglib实现
         *    c proxyTargetClass = true  总是使用 cglib实现
         *
         *
         *
         */
        Target2 target = new Target2();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target);
        factory.addAdvisor(advisor);
        factory.setInterfaces(target.getClass().getInterfaces());
        factory.setProxyTargetClass(false);
        Target2 proxy = (Target2)factory.getProxy();

        System.out.println(proxy.getClass());
        proxy.foo();
        proxy.bar();


    }
    interface I1 {
        void foo();

        void bar();
    }

    static class Target1 implements I1 {
        public void foo() {
            System.out.println("target1 foo");
        }

        public void bar() {
            System.out.println("target1 bar");
        }
    }

    static class Target2 {
        public void foo() {
            System.out.println("target2 foo");
        }

        public void bar() {
            System.out.println("target2 bar");
        }
    }
}

 

 

posted @ 2022-10-02 17:37  KwFruit  阅读(76)  评论(0编辑  收藏  举报