• spring源码AOP解析


    1、代理技术(静态代理、JDK动态代理、CGLib代理)

    静态代理:
    |-- Hello 
    |-- void say(String name);
    |-- HelloImpl implements Hello {
    voiv say(String name){
        sysout("Hello!"+name);
    }
    }
    |-- HelloProxy implents Hello {
        Hello hello; 
        HelloProxy(){
            hello = new HelloImpl();
        }
        voiv say(String name){
            before();
            sysout("Hello!"+name);
            end();
        }
        void before(){
            sysout("Before");
        }
        void after(){
            sysout("After");
        }
        
        main(String[] args){
            Hello hello = new HelloProxy();
            hello.say("Jack");
        }
    }
    JDK动态代理:
    |-- DynamicProxy implements InvocationHandler {
        Object target; 
        DynamicProxy (Object target){
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args){
            before();
            object result = method.invoke(target, args);
            after();
            return result;
        }
        ...
        
        main(String[] args){
            // 尝试1
            Hello hello = new HelloImpl();
            DynamicProxy dynamicProxy = new DynamicProxy(hello);
            Hello hello = (Hello)Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass.getInterfaces(), dynamicProxy);
            hello.say("Jack");
            
            // 尝试2
            DynamicProxy dynamicProxy = new DynamicProxy(new HelloImpl());
            Hello hello = dynamicProxy.getProxy();
            hello.say("Jack");
        }
        
        public <T> T getProxy(){
            return (T)Proxy.newProxyInstance(
                target.getClass().getClassLoader(), 
                target.getClass.getInterfaces(), 
                this
            );
        }
    }
    
    CGLib动态代理:
    |-- CGLibProxy implements MethodInterceptor {
        private static CGLibProxy instance = new CGLibProxy();
        
        private CGLibProxy() {}
        
        public CGLibProxy getInstance(){
            return instance;
        }
    
        public <T> T getProxy(Class<T> cls){
            return (T) Enhancer.create(cls, this);
        }
        public Object inercept(Object obj, Method method, Object[] args, MethodProxy proxy){
            before();
            Object result = proxy.invokeSuper(obj, args);
            after();
            return result;
        }
        ...    
        
        main(String[] args){
            // 尝试1
            CGLibProxy cgLibProxy = new CGLibProxy();
            Hello helloProxy = cgLibProxy.getProxy(HelloImpl.class);
            helloProxy.say("Jack");
            // 尝试2
            Hello helloProxy =CGLibProxy.getInstance().getProxy(HelloImpl.class);
            helloProxy.say("Jack");
        }
    }
    View Code

    2、AOP技术

    |-- interface Greeting 
    |-- void sayHello(String name);
    |-- GreetingImpl implements Greeting
    |-- sayHello(String name){
        before();
        sysout("Hello!"+name);
        after();
    }
    |-- GreetingProxy implements Greeting
    |-- GreetingImpl greetingImpl;
    |-- GreetingProxy(GreetingImpl greetingImpl) -> this.greetingImpl = greetingImpl;
    |-- sayHello(String name){
        before();
        greetingImpl.sayHello();
        after();
    }
    |-- before() -> sysout("Before");
    |-- after() -> sysout("After");
    |-- main(String[] args){
        Greeting greetingProxy = new GreetingProxy(new GreetingImpl());
        greetingProxy.sayHello("Jack");
    }
    |-- JDKDynamicProxy implements InvocationHandler {
        Object target; 
        JDKDynamicProxy (Object target){
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args){
            before();
            object result = method.invoke(target, args);
            after();
            return result;
        }
        public <T> T getProxy(){
            return (T)Proxy.newProxyInstance(
                target.getClass().getClassLoader(), 
                target.getClass.getInterfaces(), 
                this
            );
        }
        private void before(){
            sysout("Before");
        }
        private void after(){
            sysout("After");
        }
        
        main(String[] args){
            Greeting greeting = new JDKDynamicProxy(new GreetingImpl()).getProxy();
            greeting.sayHello("Jack");
        }
    }
    |-- CGLibProxy implements MethodInterceptor{
        private static CGLibProxy instance = new CGLibProxy();
            
        private CGLibProxy() {}
        
        public CGLibProxy getInstance(){
            return instance;
        }
    
        public <T> T getProxy(Class<T> cls){
            return (T) Enhancer.create(cls, this);
        }
        public Object inercept(Object obj, Method method, Object[] args, MethodProxy proxy){
            before();
            Object result = proxy.invokeSuper(obj, args);
            after();
            return result;
        }
        main(String[] args){
            Greeting greeting = CGLibProxy.getInstance().getProxy(GreetingImpl.class);
            greeting.sayHello("Jack");
        }
    }
    View Code

    3、spring AOP技术

    |-- GreetingBeforeAdvice implements MethodBeforeAdvice
        |-- before(Method method, Object[] args, Object target) throws Throwable -> sysout("Before");
    |-- AfterReturningAdvice 
        |-- afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable -> sysout("after");
    |-- GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice
        |-- before(Method method, Object[] args, Object target) throws Throwable -> sysout("Before");
        |-- afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable -> sysout("after");
    |-- GreetingAroundAdvice implements MethodInterceptor // 环绕增强(org.aopalliance.intercept.MethodInterceptor,AOP联盟)
        |-- Object invoke(MethodInvocation invocation){
            before();
            Object result = invocation.proceed();
            after();
        }
        |-- before() -> sysout("Before")
        |-- after() -> sysout("After")
    |-- main (String[] args){
            ProxyFactory proxyFactory = new ProxyFactory(); // 创建代理工厂
            proxyFactory.setTarget(new GreetingImpl()); // 射入目标类对象
            // proxyFactory.addAdvice(new GreetingBeforeAdvice()); // 添加前置增强
            // proxyFactory.addAdvice(new AfterReturningAdvice()); // 添加后置增强
            // proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice()); // 添加前后置增强
            proxyFactory.addAdvice(new GreetingAroundAdvice()); // 添加环绕增强
            
            Greeting greeting = (Greeting)proxyFactory.getProxy(); // 从代理工厂获取代理对象
            greeting.sayHello("Jack"); // 调用代理方法
        }
    |-- 配置文件-spring.xml
        <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
        <context:componet-scan base-package="aop.demo"/> 
        <!-- 配置一个代理 --> 
        <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="interfaces" value="aop.Greeting"></property><!-- 需要代理的接口 -->
            <property name="target" value="greetingImpl"></property><!-- 接口实现类 -->
            <!-- <property name="target" value="greetingAroundAdvice"></property> -->
            <property name="interceptorNames">
                <list>
                    <value>greetingAroundAdvice</value>
                </list>
            </property>
        </bean>
        
        spring2.5+特性,@Component
        @Component
        public calss GreetingImpl implements Greeting {
            ...
        }
        --> 
        <bean id="xxx" class="xxx">
    |-- 客户端调用
        |-- main(String[] args){
                ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml");
                Greeting greeting = (Greeting)context.getBean("greetingProxy");
                greeting.sayHello("Jack");
            }
    |-- 抛出增强-ThrowsAdvice
        |-- GreetingThrowAdvice implements ThrowsAdvice {
                public void afterThrowing(Method method, Object[] args, Object target, Exception e){
                    sysout("--------- Throw Exception ---------");
                    sysout("Target Class: " + target.getClass().getName());
                    sysout("Method Name: " + method.getName());
                    sysout("Exception Message: " + e.getMessage());
                    sysout("-----------------------------------");
                }
            }
    |-- 引入增强
        |-- interface Apology 
            |-- void saySorry(String name);
        |-- @Component
            GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology {
                @Override 
                public Object invoke(MethodInvocation invocation) throws Throwable{
                    return super.invoke(invocation);
                }
                
                @Overrice
                public void saySorry(String name){
                    sysout("Sorry! + name);
                }
            }
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/> 
            <!-- 配置一个代理 --> 
            <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                <property name="interfaces" value="aop.demo.Apology"></property><!-- 需要动态实现的接口 -->
                <property name="target" value="greetingImpl"></property><!-- 目标类 -->
                <property name="interceptorNames" value="greetingIntroAdvice"></property> <!-- 引入增强 -->
                <property name="proxyTargetClass" value="true"/> <!-- 代理目标类(默认为false,代理接口)-->
            </bean>
        |-- 调用
            |-- main(String[] args){
                ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml");
                GeetingImpl greetingImpl = (GeetingImpl)context.getBean("greetingProxy"); // 转型为目标类,而非它的接口
                greetingImpl.sayHello("Jack");
                
                Apology apology = (Apology) greetingImpl; // 将目标类型强制向上转型为Apology接口(这就是引入增强给我们带来的特性,也就是“接口动态实现”功能)
                apology.saySorry("Jack");
            }
    |-- AOP 切面
        |-- @Component
            public class GreetingImpl implements Greeting {
                @Override
                public void sayHello(){
                    sysout("Hello!" + name);
                }
                
                public void goodMorning(String name){
                    sysout("Good Morning!" + name);
                }
                public void goodNight(String name){
                    sysout("Good Night!" + name);
                }
            }
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/> 
            <!-- 配置一个切面 -->
            <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                <property name="advice" value="greetingAroundAdvice"></property> <!-- 增强 -->
                <property name="pattern" value="aop.demo.GreetingImpl.good.*"></property> <!-- 切点(正则表达式) -->
            </bean>
            
            <!-- 配置一个代理 --> 
            <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                <property name="target" value="greetingImpl"></property><!-- 目标类 -->
                <property name="interceptorNames" value="greetingAdvisor"></property><!-- 切面 -->
                <property name="proxyTargetClass" value="true"/> <!-- 代理目标类(默认为false,代理接口)-->
            </bean>
    |-- AOP自动代理(每一个类都需要配置切面太麻烦,因此需要自动生成代理)
        |-- 配置文件-spring.xml
        <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="target" value="*Impl"></property><!-- 目标类 -->
            <property name="interceptorNames" value="greetingAroundAdvice"></property><!-- 增强 -->
            <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
        </bean>
        *Impl -> 不清楚Bean实现了多少接口,不能代理接口,只能代理类。
        |-- 匹配到目标类的指定方法
            |-- 配置文件-spring.xml
                <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
                    <!-- <property name="target" value="*Impl">--></property><!-- 目标类 -->
                    <!-- <property name="interceptorNames" value="greetingAroundAdvice"></property>--><!-- 增强 -->
                    <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
                </bean>
                --> 
                <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                    <property name="advice" ref="greetingAroundAdvice"></property> <!-- 增强 -->
                    <property name="pattern" value="aop.demo.GreetingImpl.good.*"></property> <!-- 切点(正则表达式) -->
                </bean>
                <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
                    <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
                </bean>
    
    总结:
        CGLib代理:创建代理速度慢,创建代理后运行速度快(系统初始化创建代理备用最佳)
        JDK动态代理:创建代理速度快,运行速度慢
        
    |-- spring + AspectJ(Advisor)
    |-- 普通demo
        |-- @Aspect
            @Component
            public class GreetingAspect {
                @Arount("execution(* aop.demo.GreetingImpl.*(..))")
                public Object around(ProceedingJoinPoint pjp) throws Throwable {
                    before();
                    Object result = pjp.proceed();
                    after();
                    return result;
                }
                public void before(){
                    sysout("Before");
                }
                public void after(){
                    sysout("after");
                }
            }
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/> 
            <aop:aspect-autoproxy proxy-target-class="true" />    
    |-- 基于注解
        |-- @Target(ElementType.METHOD)
            @Retention(RetentionPolicy.RUNTIME)
            public @Interface Tag {
            }
        |-- @Aspect
            @Component
            public class GreetingAspect {
                @Arount("@Annotation(aop.demo.Tag)")
                public Object around(ProceedingJoinPoint pjp) throws Throwable {
                    ...
                }
                ...
            }
        |-- @Component
            public class GreetingImpl implements Greeting {
                @Tag
                @Override 
                public void sayHello(String name){
                    sysout("Hello!" + name);
                }
                ...
            }
        |-- 实现引入增强
            |-- @Aspect
                @Component
                public class GreetingAspect {
                    
                    @DelareParents(value="aop.demo.GreetingImpl",defaultImpl="ApologyImpl.class")
                    private Apology apology;
                }
            |-- ApologyImpl implements Apology {
                    
                    @Override
                    public void saySorry(String name){
                        sysout("Sorry!" + name);
                    }
                    main(String[] args){
                        ApplicationContext context = new ClassPathXmlApplicationContext("aop/demp/spring.xml");
                        Greeting greeting = context.getBean("greetingImpl");
                        greeting.sayHello("Jack");
                        Apology apology = (Apology) greeting;
                        apology.saySorry("Jack");
                    }
                }
            
    |-- 基于配置
        |-- 配置文件-spring.xml
            <!-- 扫描指定包(将带有@componet注解类自动定义为Spring bean) -->
            <context:componet-scan base-package="aop.demo"/>
            <beans ...>
                
                <bean id="greetingImpl" class="aop.demo.GreetingImpl" />
                <bean id="greetingAspect" class="aop.demo.GreetingAspect" />
                <aop:config>
                    <aop:aspect ref="greetingAspect">
                        <aop:around method="around" pointcut="execution (* aop.demo.GreetingImpl.*(..))"/>
                    </aop:aspect>
                </aop:config>
            </beans>
    View Code

    4、开发aop框架

    |-- 定义注解类:
    |-- @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @Interface Aspect {
        Class<? extends Annotion> value();
    }
    |-- 搭建代理框架
    |-- interface Proxy { 代理接口
        // 执行链式代理:可将多个代理通过一条链子串起来,一个个地去执行,执行顺序取决于添加到链上的先后顺序
        Object doProxy(ProxyChain proxyChain) throws Throwable;
    }
    |-- class ProxyChain // 代理链
    |-- Class<?> targetClass;
    |-- Object targetObject;
    }-- Method targetMethod;
    |-- MethodProxy methodProxy;
    }-- Object[] methodParams;
    |-- List<Proxy> proxyList = new ArrayList<>();
    |-- int proxyIndex=0;
    |-- ProxChain(Class<?> targetClass,Object targetObject,Method targetMethod,MethodProxy methodProxy,Object[] methodParams,List<Proxy> proxyList){
            this.targetClass = targetClass;
            ...
        }
    |-- getMethodParams() -> return methodParams;
    |-- getTargetClass() -> return targetClass;
    |-- getTargetMethod() -> return targetMethod;
    |-- Object doProxyChain() throws throwable{
            Object methodResult;
            if (proxyIndex < proxyList.size()){
                methodResult = proxyList.get(proxyIndex++).doProxy();
            } else {
                methodResult = methodProxy.invokeSuper(targetObject, methodParams);
            }
            return methodResult;
        }
    |-- 添加pom.xml依赖
    <!-- cglib 依赖-->
    <grouId>cglib<groupId>...
    |-- class ProxyManger // 代理管理类
    |-- <T> T createProxy(final Class<?> targetClass, final List<Proxy> proxyList){
            return (T) Enhancer.create(targetClass, new MethodInterceptor(){
                @Overrice
                public Object intercept(Object targetObject, Method targetMethod, 
                    Object[] methodParams, MethodProxy methodProxy){
                    return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList);
                }
            });
        }
    |-- public abstract calss AspectProxy implements Proxy { // 切面代理
        @Override
        public final Object doProxy(ProxyChain proxyChain) throws throwable {
            Object result = null;
            Class<?> cls = proxyChain.getTargetClass();
            Method method = proxyChain.getTargetMethod();
            Object[] params = proxyChain.getMethodParams();
            begin();
            try {
                if (intercept(cls, method, params)){
                    before(cls, method, params);
                    result = proxyChain.doProxyChain();
                    after(cls, method, params);
                } else {
                    return proxyChain.doProxyChain();
                }
            } catch(Exception e){
                logger.error("proxy failure", e);
                error(cls, method, params, e);
                throw e;
            } finally {
                end();
            }
        }
        public void begin(){
        }
        public void end(){
        }
        public boolean intercept(Class<?> cls, Method method, Object[] params) throws Throwable {
            return true;
        }
        public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
        }
        public void after(Class<?> cls, Method method, Object[] params) throws Throwable {
        }
        public void error(Class<?> cls, Method method, Object[] params, Throwable e){
        }
    }
    |-- @Aspect(Controller.class)
    ControllerAspect extends AspectProxy{ // 拦截Controller    所有方法
        private long begin;
        @Override
        public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
            begin = System.currentTimeMillis();
        }
        @Override
        public void after(Class<?> cls, Method method, Object[] params) throws Throwable {
            sysout(System.currentTimeMillis()-begin);
        }
    }
    |-- BeanHelper {
        ...
        // 设置bean实例 
        public static void setBean(Class<?> cls, Object obj){
            BEAN_MAP.put(cls, obj);
        }
    }    
    |-- ClassHelper {
        ...
        // 获取某父类(或接口)的所有子类(或实现类)
        public static Set<Class<?>> getClassSetBySuper(Class<?> superClass){
            Set<Class<?>> classSet = new HashSet<Classs<?>();
            for(Class<?> cls : CLASS_SET){
                if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)){
                    classSet.add(cls);
                }
            }
        } 
        // 获取应用包名下带有注解的所有类
        public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotionClass){
            Set<Class<?>> classSet = new HashSet<Classs<?>();
            for(Class<?> cls : CLASS_SET){
                if (superClass.isAnnotationPresent(annotionClass)){
                    classSet.add(cls);
                }
            }
        }
        ...
    }
    |-- AopHelper {
        ...
        private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception {
            Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
            Class<? extends annotation> annotation = aspect.value();
            if (annotation != null && !annotation.equals(Aspect.class)){
                targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
            }
            return targetClassSet;
        }
        private static Map<Class<?>>,Set<Class<?>>> createProxyMap() throws Exception {
            Map<Class<?>>,Set<Class<?>>> proxyMap = new HashMap<Class<?>>,Set<Class<?>>>();
            Set<Class<?>> proxyClassSet = ClassHelper.getClassSetByAnnotation(AspectProxy.class);
            for(Class<?> proxyClass : proxyClassSet){
                if (proxyClass.isAnnotationPresent(Aspect.class)){
                    Aspect aspect = proxyClass.getAnnotation(Aspect.class);
                    Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
                    proxyMap.put(proxyClass, targetClassSet);
                }
            }
            return proxyMap;
        }    
        private static Map<Class<?>,List<Proxy>> createTargetMap(Map<Class<?>>,Set<Class<?>>> proxyMap) throws Exception {
            Map<Class<?>,List<Proxy>> targetMap = new HashMap<Class<?>,List<Proxy>>();
            for(Map.Entry<Class<?>>,Set<Class<?>>> proxyEntry : proxyMap.entrySet()){
                Class<?> proxyClass = proxyEntry.getKey();
                Set<Class<?> targetClassSet = proxyEntry.getValue();
                for(Class<?> targetClass : targetClassSet){
                    Proxy proxy = (Proxy) targetClass.newInstance();
                    if (targetMap.contains(targetClass)){
                        targetMap.get(targetClass).add(proxy);
                    } else {
                        List<Proxy> proxyList = new ArrayList<Proxy>();
                        proxyList.add(proxy);
                        targetMap.put(targetClass, proxyList);
                    }
                }
            }
        }
        
        static {
            try {
                Map<Class<?>>,Set<Class<?>>> proxyMap = createProxyMap();
                Map<Class<?>,List<Proxy>> targetMap = createTargetMap(proxyMap);
                for(Map.Entry<Class<?>,List<Proxy>> targetEntry : targetMap.etrySet()){
                    Class<?> targetClass =targetEntry.getKey();
                    List<Proxy> proxyList = targetEntry.getValue();
                    Object proxy = ProxyManager.createProxy(targetClass, proxyList);
                    BeanHelper.setBean(targetClass, proxy);
                }
            } catch(Exception e){
                Logger.error("aop failure", e);
            }
        }
    }
    |-- HelperLoader {
        public static void init(){
        
            Class<?>[] classList = {
                ClassHelper.class, 
                BeanHelper.class,
                AopHelper.class,
                IocHelper.class,
                ControllerHelper.class
            };
            for(Class<?> cls : classList){
                ClassUtil.loadClass(cls.getName(), true);
            }
        }
    }
    View Code

    gitee地址:https://gitee.com/linestyle007/jucdemo2

    博客地址:https://linestyle007.gitee.io/

    github地址:https://github.com/line007/jucdemo2

  • 相关阅读:
    Java 密钥库 证书 公钥 私钥
    Theos小例子
    armbian禁用zram
    常见JS混淆器和特征
    命令行工具收藏
    python中生成器的两段代码
    把mysql数据库从windows迁移到linux系统上的方法
    【转载】使用Flink低级处理函数ProcessFunction
    spark读取压缩文件
    SpringBoot系列——validation参数校验
  • 原文地址:https://www.cnblogs.com/ice-line/p/9967369.html
Copyright © 2020-2023  润新知