15AOP从 @Aspect 到 Advisor

两种切面的实现

package com.butch.a17;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

public class A17 {


    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("aspect1",Aspect1.class);
        context.registerBean("config",config.class);
        //加后置处理器
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.refresh();
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }

    }

    static class Targer1{
        public void foo(){
            System.out.println("target1 foo");
        }
    }
    static class Targer2{
        public void bar(){
            System.out.println("target2 bar");
        }
    }


    //aspect切面
    @Aspect
    static class Aspect1{

        @Before("execution(* foo())")
        public void before(){
            System.out.println("aspect1 before.....");
        }

        @After("execution(* foo())")
        public void after(){
            System.out.println("aspect1 after.....");
        }

    }

    //advisor切面
    @Configuration
    static class config{

        @Bean
        public Advisor advisor3(MethodInterceptor advice3){
            AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
            aspectJExpressionPointcut.setExpression("execution(* foo())");
            //第一个参数是切点 第二个参数是通知
            return new DefaultPointcutAdvisor(aspectJExpressionPointcut,advice3);
        }

        @Bean
        public MethodInterceptor advice3(){
            return new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                    System.out.println("advisor3 before.....");
                    Object proceed = methodInvocation.proceed();
                    System.out.println("advisor3 after.....");
                    return proceed;
                }
            };
        }

    }

}

代理创建器实现原理

AnnotationAwareAspectJAutoProxyCreator

这是一个bean后置处理器,即为AOP的实现原理

  1. 发现切面对象

  2. 高级切面转低级切面,创建代理

findEligibleAdvisors
  • 有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如本例 A17 中的 advisor3

  • 有【资格】的 Advisor 另一部分是高级的, 由解析 @Aspect 后获得

wrapIfNecessary
  • 是否有必要创建的代理,它内部调用 findEligibleAdvisors, 只要返回集合不空, 则表示需要创建代理

  • 它的调用时机通常在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行

总结

  1. 在容器中寻找目标类是否有匹配的切面,高级切面转化为低级

  2. 根据1返回的集合,不为空则创建代理对象

package org.springframework.aop.framework.autoproxy;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

import java.util.List;

public class A17 {


    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("aspect1",Aspect1.class);
        context.registerBean("config",config.class);
        //加后置处理器
        context.registerBean(ConfigurationClassPostProcessor.class);
        //bean后处理器
        //位置  bean 创建-> (*) 依赖注入 -> (*) 初始化
        context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
        context.refresh();
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }

        AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
//        A17_1 a17_1 = new A17_1();
        //第一个参数为目标类 找出目标类中有能使用增强的切面
        List<Advisor> target1 = creator.findEligibleAdvisors(Targer1.class, "target1");
//        List<Advisor> target1 = a17_1.findCandidateAdvisors(Targer1.class, "target1");
        System.out.println("================================");
//        for (Advisor advisor : target1) {
//            System.out.println("advisor = " + advisor);
//        }
        Object o1 = creator.wrapIfNecessary(new Targer1(), "target1", "target1");
        //o1为代理
        System.out.println("o1.getClass() = " + o1.getClass());
        //o2非代理
        Object o2 = creator.wrapIfNecessary(new Targer2(), "target2", "target2");
        System.out.println("o2.getClass() = " + o2.getClass());
    }

    static class Targer1{
        public void foo(){
            System.out.println("target1 foo");
        }
        
    }
    static class Targer2{
        public void bar(){
            System.out.println("target2 bar");
        }
    }


    //aspect切面
    @Aspect
    static class Aspect1{

        @Before("execution(* foo())")
        public void before(){
            System.out.println("aspect1 before.....");
        }

        @After("execution(* foo())")
        public void after(){
            System.out.println("aspect1 after.....");
        }

    }

    //advisor切面
    @Configuration
    static class config{

        @Bean
        public Advisor advisor3(MethodInterceptor advice3){
            AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
            aspectJExpressionPointcut.setExpression("execution(* foo())");
            //第一个参数是切点 第二个参数是通知
            return new DefaultPointcutAdvisor(aspectJExpressionPointcut,advice3);
        }

        @Bean
        public MethodInterceptor advice3(){
            return new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                    System.out.println("advisor3 before.....");
                    Object proceed = methodInvocation.proceed();
                    System.out.println("advisor3 after.....");
                    return proceed;
                }
            };
        }

    }

}

代理创建的时机

package org.springframework.aop.framework.autoproxy;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

import javax.annotation.PostConstruct;

public class A17_1 {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean(Config.class);
        //加后置处理器
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.refresh();
        context.close();
    }


    @Configuration
    static class Config{

        @Bean//代理创建器
        public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator(){
            return new AnnotationAwareAspectJAutoProxyCreator();
        }

        @Bean//处理@autowired注解
        public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor(){
            return new AutowiredAnnotationBeanPostProcessor();
        }

        @Bean//处理@postconstruct、
        public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor(){
            return new CommonAnnotationBeanPostProcessor();
        }


        @Bean//切面
        public Advisor advisor(MethodInterceptor advice3){
            AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
            aspectJExpressionPointcut.setExpression("execution(* foo())");
            //第一个参数是切点 第二个参数是通知
            return new DefaultPointcutAdvisor(aspectJExpressionPointcut,advice3);
        }

        @Bean//通知
        public MethodInterceptor advice3(){
            return new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                    System.out.println("advisor3 before.....");
                    Object proceed = methodInvocation.proceed();
                    System.out.println("advisor3 after.....");
                    return proceed;
                }
            };
        }


        @Bean
        public Bean1 bean1(){
            return new Bean1();
        }
        @Bean
        public Bean2 bean2(){
            return new Bean2();
        }

    }

    static class Bean1 {
        public void foo() {
        }

        public Bean1() {
            System.out.println("bean1实例化构造方法........");
        }

        @PostConstruct
        public void init() {
            System.out.println("bean1的初始化init方法................");
        }
    }



    static class Bean2 {
        @Autowired
        public void setBean1(Bean1 bean1){
            System.out.println("bean2依赖注入bean1..................." + bean1.getClass());
        }

        public Bean2() {
            System.out.println("bean2实例化构造方法........");
        }

        @PostConstruct
        public void init() {
            System.out.println("bean2的初始化init方法................");
        }
    }

}

bean2依赖bean1的时候,并且bean1也依赖于bean2,即为循环依赖,bean1中有需要增强的方法,代理对象则是在bean1初始化之后创建,bea2则注入bea1的代理对象

  1. bean1构造

  2. 注入bean2,bean2没有,暂停进入bean2生命周期

  3. bean2实例化方法

  4. bean2依赖注入bean1,由于bean1中的方法需要增强,因此需要注入代理对象,在bean实例化后,创建bean1的代理对象

  5. bean2的初始化

  6. bean1的依赖注入

  7. bean1的初始化

总结

  1. 无循环依赖代理创建在初始化之后

  2. 有循环依赖时 创建于的实例化之后依赖注入之前,并且存于二级缓存中

  3. 依赖注入及初始化阶段不应增强,如set方法应该调用原始方法的set

高级切面转低级切面

共五种通知类型,在findEligibleAdvisors 方法中,转换为对应低级切面

  1. @Before 前置通知会被转换为原始的 AspectJMethodBeforeAdvice 形式, 该对象包含了如下信息

    1. 通知代码从哪儿来

    2. 切点是什么

    3. 通知对象如何创建, 本例共用同一个 Aspect 对象

  2. 类似的还有

    1. AspectJAroundAdvice (环绕通知)

    2. AspectJAfterReturningAdvice

    3. AspectJAfterThrowingAdvice (环绕通知)

    4. AspectJAfterAdvice (环绕通知)

package org.springframework.aop.framework.autoproxy;

import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectInstanceFactory;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class A18 {
    public static void main(String[] args) {
        AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new Aspect());
        List<Advisor> list = new ArrayList<>();
        for (Method declaredMethod : Aspect.class.getDeclaredMethods()) {
            if (declaredMethod.isAnnotationPresent(Before.class)) {
                //解析切点
                String value = declaredMethod.getAnnotation(Before.class).value();
                AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
                aspectJExpressionPointcut.setExpression(value);
                //转为对应底层通知类
                AspectJMethodBeforeAdvice aspectJMethodBeforeAdvice = new AspectJMethodBeforeAdvice(declaredMethod,aspectJExpressionPointcut,factory);
                //转为低级切面
                DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJMethodBeforeAdvice);
                list.add(defaultPointcutAdvisor);

            }
        }
        for (Advisor advisor : list) {
            System.out.println("advisor = " + advisor);
        }
    }

    static class Aspect{
        @Before("execution(* foo")
        public void before1() {
            System.out.println("===========before1========");
        }
        @Before("execution(* foo")
        public void before2() {
            System.out.println("===========before2========");
        }
    }
    static class Target{
        public void foo(){
            System.out.println("target foo===============");
        }
    }
}

总结:

  1. 拿到高级切面类,通过反射获取所有的方法

  2. 检查方法上是否包含通知类型的注解

  3. 解析注解的切点表达式,设置底层的切点对象

  4. 根据不同通知类型注解实现对应底层通知的实现,最终都是转化为环绕通知类型

  5. 通过通知和切点实现底层切面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值