Spring AOP(五)

AOP

定义:

​ Spring AOP是Spring用来增强bean的一种方式,他基于动态代理实现。有分为基于接口实现的JDK动态代理基于继承实现的CGLIB动态代理

概念术语:

术语解释
目标对象 target要增强的对象包含主业务逻辑的类对象
连接点 Join point代表要增强的方法
切面 Aspect切面是指切面类
管理增强的公共行为代码(通知)和切入方式(切点)
切点 Pointcut用于匹配连接点
决定要不要织入的表达式
匹配规则:AspectJ
通知 Advice在某个连接点执行的动作 增强方法
分为“around”,“before”,“after”…
拦截器作为通知模型
织入 Weaving通知切入连接点 的过程
顾问 Advisor用于管理 切点和通知
引入 Introductions将其他接口和实现 动态引入 到targetClass中

在这里插入图片描述

例子

静态代理例子

  1. 首先定义target类和接口
/**
 * 计算类接口
 */
public interface Calculate {

    /**
     * 加法
     */
    int add(int numA, int numB);

    /**
     * 减法
     */
    int sub(int numA, int numB);

    /**
     * 除法
     */
    int div(int numA, int numB);

    /**
     * 乘法
     */
	int multi(int numA, int numB);
    
}

/**
 * 计算器实例target
 */
@Component
public class TulingCalculate implements Calculate {

    public int add(int numA, int numB) {
        System.out.println("执行目标方法:add");
        System.out.println(1/0);
        return numA+numB;
    }

    public int sub(int numA, int numB) {
        System.out.println("执行目标方法:reduce");
        return numA-numB;
    }

    public int div(int numA, int numB) {
        System.out.println("执行目标方法:div");
        return numA/numB;
    }

    public int multi(int numA, int numB) {
        System.out.println("执行目标方法:multi");
        return numA*numB;
    }
    
}
  1. 定义advice或Interceptor 增强的公共代码
/**
 * 定义增强的公共代码,记录日志为例
 */
public class TulingLogAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        String methodName = method.getName();
        System.out.println("执行目标方法【"+methodName+"】的<前置通知>,参数"+ Arrays.asList(args));
    }
}


/**
 * 定义拦截器,来增强方法
 */
public class TulingLogInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println(getClass()+"调用方法前");
        Object ret=invocation.proceed();
        System.out.println(getClass()+"调用方法后");
        return ret;
    }

}
  1. 通过配置类创建一个==静态代理==
@Configuration
@EnableAspectJAutoProxy
public class EalyAopMainConfig {
    // 被代理对象,注入IOC
    @Bean
    public Calculate myCalculate() {
        return new MyCalculate();
    }

    // Advice 方式
    @Bean
    public TulingLogAdvice tulingLogAdvice(){
        return new TulingLogAdvice();
    }

    // Interceptor方式 , 类似环绕通知
    @Bean
    public TulingLogInterceptor tulingLogInterceptor() {
        return new TulingLogInterceptor();
    }
  
    // 注入一个静态代理!
    @Bean
    public ProxyFactoryBean calculateProxy(){
        ProxyFactoryBean userService=new ProxyFactoryBean();
        // 设置**切面** 就是增强的代码
        userService.setInterceptorNames("tulingLogAdvice","tulingLogInterceptor");
        // 设置**目标对象** 就是要增强的类
        userService.setTarget(tulingCalculate());
        return userService;
    }
}
  1. 执行
public static void main(String[] args) { 
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EalyAopMainConfig.class);
    // 还要知道代理的名字calculateProxy,才能获得代理对象
    Calculate calculateProxy = ctx.getBean("calculateProxy",Calculate.class);
    // 调用目标方法
    calculateProxy.div(1,1);
}

缺点:

  • bean单一目标 —— 通过静态代理的方式,导致 只能指定单一target 的AOP,多个bean要手动创建多个ProxyFactoryBean
  • 拦截粒度大 —— 通过这种方式,导致拦截了目标类中的所有方法

细粒度拦截:

// 配置类修改为
@Bean
public NameMatchMethodPointcutAdvisor tulingLogAspect() {
    // 通知者(Advisor):是经过包装后的细粒度控制方式。
    NameMatchMethodPointcutAdvisor advisor=new NameMatchMethodPointcutAdvisor();
    // 通知(Advice)  :有增强方法的那个类
    advisor.setAdvice(tulingLogAdvice());
    // 匹配目标类的方法
    advisor.setMappedNames("div");
    return advisor;
}

/**
 * FactoryBean方式单个: ProxyFactoryBean
 *  控制粒度到方法
 */
@Bean
public ProxyFactoryBean calculateProxy(){
    ProxyFactoryBean userService=new ProxyFactoryBean();
    // 设置 **切面**,增强的代码通过 **通知者** 来包装
    userService.setInterceptorNames("tulingLogAspect"); 
    // 设置目标类
    userService.setTarget(tulingCalculate());
    return userService;
}

执行

public static void main(String[] args) { 
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EalyAopMainConfig.class);
    // 还要知道代理的名字calculateProxy,才能获得代理对象
    Calculate calculateProxy = ctx.getBean("calculateProxy",Calculate.class);
    // 调用目标方法
    calculateProxy.div(1,1);
}

好处:

​ 通过通知者Advisor配置,可以将拦截粒度从 类层面 降低到 方法层面,之拦截特定方法

缺点
  • 每一个bean都配置一个静态代理
  • getBean也需要获取代理类 【calculateProxy】

很不方便

动态代理

​ 为了避免麻烦,每一个类都要创建一个代理而且getBean要去拿【calculateProxy】 反人类

我们可以通过autoproxy来让Spring自动生成代理来拦截方法

改进静态代理:

// 去掉原来的代理bean:calculateProxy 【ProxyFactoryBean这种静态配置】
// 用BeanNameAutoProxyCreator 这种动态配置

@Bean
public BeanNameAutoProxyCreator autoProxyCreator() {
    BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
    // 这就是 **目标对象们targets**    设置需要代理的bean们
    beanNameAutoProxyCreator.setBeanNames("tuling*");

    //设置 **通知** (这些拦截器是有先后顺序的)  就是你动态代理要给他们执行的方法的bean咯~
    beanNameAutoProxyCreator.setInterceptorNames("tulingLogInterceptor");
    return beanNameAutoProxyCreator;
}

执行

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EalyAopMainConfig.class);
    // 这时候只需要按bean名字来get就好了!!! 不需要再管是 三姑代理还是六婆代理 啊!! 方便得要死
    Calculate tulingCalculate = ctx.getBean("tulingCalculate",Calculate.class);
    tulingCalculate.div(1,1); 
}
好处
  • 获取bean代理方便 —— 想拿bean对应的代理,直接用bean名来获取就行,不需要再知道是哪个xx代理我了
  • 给多个target创建代理 —— 一次性可以对符合正则表示式的目标对象target创建代理噢!不需要一个一个创建那么麻烦了
坏处
  • 粒度大 —— 拦截整个类,不能拦截到具体方法
加强版
// RegexpMethodPointcutAdvisor 按正则匹配类
@Bean
public RegexpMethodPointcutAdvisor tulingLogAspectInterceptor() {
    RegexpMethodPointcutAdvisor advisor=new RegexpMethodPointcutAdvisor();
    // 设置 **advice**
    advisor.setAdvice(tulingLogInterceptor());
    // 正则匹配 target们!
    advisor.setPattern("tuling.TulingCalculate.*");
    return  advisor;
}

Spring AOP使用

  1. 开启AOP —— @EnableAspectJAutoProxy

  2. 编写切面类 —— @Aspect

  3. 编写切点表达式 —— @Pointcut(“execution(返回值 包名.类名.方法名(参数类型) )”)

    @Pointcut("execution(* com.summer.circulardependencies.*Controller.*(..))")
    
  4. 编写通知 —— @Around、@Before、@After、@AfterReturning、@AfterThrowing

AOP原理

定义:

​ 在Spring中,怎么给一个bean对象生成动态代理呢?

​ 如果我们要对bean进行增强,那么我们是不是需要去找一个增强的处理器? 没错,就是BeanPostProcessor

​ BeanPostProcessor是一个接口,那么AOP动态代理由谁实现的呢?由AbstractAutoProxyCreator类实现的

正常的AOP

初始化后进行AOP

  • 初始化后 —— applyBeanPostProcessorsAfterInitialization() 里面调用BeanPostProcessor

源码:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        // 1. 循环取出所有Bean后置处理器,找到AOP的那个后置处理器
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

// AbstractAutoProxyCreator类
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 1. 这里是判断之前有没有创建AOP,就是循环依赖的时候
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 2. 如果没有创建,那么就去创建AOP
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

    //  如果有 **通知者**,去创建
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 3. 创建AOP动态代理
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

循环依赖的AOP

提前进行AOP —— 实例化后进行AOP

  • 实例化后 —— getEarlyReference() 里面调用BeanPostProcessor

源码:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
            // 1. 获取早期引用
            exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
        }
    }
    return exposedObject;
}

// AbstractAutoProxyCreator类
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
    // 2. 提供一个标识,告诉后面的正常AOP,我已经创建AOP了,你不要创建了
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    this.earlyProxyReferences.put(cacheKey, bean);
    // 3. 循环依赖,那么它一定是先于正常创建AOP的,所以不用判断是否已经创建AOP,直接创建
    return wrapIfNecessary(bean, beanName, cacheKey);
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

    //  如果有 **通知者**,去创建
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 3. 创建AOP动态代理
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

AOP怎么注入到容器中?

定义:

​ 我们知道,AOP是通过@EnableAspectJAutoProxy 注解进行开启的,点进去会发现有@Import(AspectJAutoProxyRegistrar.class)这个类的导入

是什么时候进行导入的?

​ 它是通过配置类被解析的时候

​ 配置类可以获取自己的**@Import注解load**注册为Bean定义的这个时候导入的

源码

// 1. 配置类被解析时,通过reader来加载配置类上的注解的依赖
this.reader.loadBeanDefinitions(configClasses);

// Reader来读取
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    for (ConfigurationClass configClass : configurationModel) {
        // 配置类有可能是一个set集合,就是不止一个,那么循环遍历
        loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}

// Reader读取
private void loadBeanDefinitionsForConfigurationClass(
    ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

    if (configClass.isImported()) {
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }

    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    // 2. 从ImportBeanDefinitionRegistrar里面加载bean定义
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

// Reader读取
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
    // 3. 这里就是遍历所有实现了ImportBeanDefinitionRegistrar这个接口的实现类,然后去注册他们
    registrars.forEach((registrar, metadata) ->
                       registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}

// ImportBeanDefinitionRegistrar接口,
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
                                     BeanNameGenerator importBeanNameGenerator) {
	// 4. 调用实现类的registerBeanDefinitions()方法
    registerBeanDefinitions(importingClassMetadata, registry);
}
  1. 在配置类被解析时,执行reader的loadBeanDefinitions()
  2. 执行loadBeanDefinitionsFromRegistrars()
    • 含义是从Registrars里面加载bean定义,就是如果有实现了ImportBeanDefinitionRegistrar这个接口的,遍历这些实现类,获取他们的bean定义
  3. 遍历,注册实现了ImportBeanDefinitionRegistrar接口的实现类,AOP的类,刚好实现了这个接口
  4. 接口默认实现,调用实现类registerBeanDefinitions()方法

AOP的实现类

真正开始创建AOP这个类AspectJAutoProxyRegistrar的逻辑

public void registerBeanDefinitions(
    AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	// 1. 关注这个方法,进行注册AOP
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    AnnotationAttributes enableAspectJAutoProxy =
        AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}
  1. 方法registerAspectJAnnotationAutoProxyCreatorIfNecessary()点进去是一个门面方法,一直进去,真正干活的方法registerOrEscalateApcAsRequired()
private static BeanDefinition registerOrEscalateApcAsRequired(
    Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

    // 1. 一开始Bean工厂肯定是没有这个AnnotationAwareAspectJAutoProxyCreator类的,现在才去创建
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }

    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 2. 去创建AnnotationAwareAspectJAutoProxyCreator类
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}
  1. AUTO_PROXY_CREATOR_BEAN_NAME这个常量对应的类就是这个 AnnotationAwareAspectJAutoProxyCreator
  2. 因为方法一开始没有包含 AnnotationAwareAspectJAutoProxyCreator类,所以要去注册这个类

实例化

AnnotationAwareAspectJAutoProxyCreator类经过上面步骤,已经注册为Bean定义了,它有两个特点

  • 实现了BeanPostProcessor接口
  • 实现了Ordered接口
  • 实现了Aware接口

在看 AnnotationAwareAspectJAutoProxyCreator类 实例化之前,我们先看看它的继承结构

在这里插入图片描述

​ 根据bean的生命周期,我们可以知道,Spring在初始化AnnotationAwareAspectJAutoProxyCreator这个类的时候,会调用BeanFactoryAware的setBeanFactory()方法支持程序员拿到 BeanFactory 并做相应的响应操作

源码:

// 父类 AbstractAdvisorAutoProxyCreator 
// 在生命周期回调的时候,调用了setBeanFactory()这个方法
@Override
public void setBeanFactory(BeanFactory beanFactory) {
    // 设置bean工厂
    super.setBeanFactory(beanFactory);
    // 1. 调用initBeanFactory()方法,由AnnotationAareAspectAutoProxyCreator实现
    initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

// 子类 AnnotationAareAspectAutoProxyCreator
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.initBeanFactory(beanFactory);
    if (this.aspectJAdvisorFactory == null) {
        this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
    }
    this.aspectJAdvisorsBuilder =
        new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
  1. 调用setBeanFactory(),因为AnnotationAwareAspectJAutoProxyCreator没有重写该方法,所以往上找,找到实现该方法的AbstractAdvisorAutoProxyCreator
  2. 调用initBeanFactory(),因为AnnotationAwareAspectJAutoProxyCreator重写了该方法,所以直接执行本类的该方法
  3. BeanFactoryAspectJAdvisorsBuilderAdapter这里实例化了一个 Bean工厂切面通知建造者适配者!它是负责从bean工厂查找 切面类,并将其封装为一个一个Advisor的列表 很重要

小结:

这里就将我们需要的类AnnotationAareAspectAutoProxyCreator给他实例化出来了,接下来就是执行它

什么时候封装Advisors?

在第一次创建普通Bean的时候,也就是实例化剩下的bean时,会调用上面的AdvisorsBuilder去扫描bean,并且将切面类给扫描读取,封装Advisors

在这里插入图片描述

在创建bean的时候,会回调方法,再找候选通知者时findCandidateAdvisors()方法中,缓存无法找到Advisors,就会去创建Advisors

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;
	// 1. 第一次进来,肯定没有切面类被创建
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                // 2. 获取所有的Bean定义名字
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }

                    Class<?> beanType = this.beanFactory.getType(beanName, false);
                    if (beanType == null) {
                        continue;
                    }
                    // 3. 判断类是否有 @Aspect注解
                    if (this.advisorFactory.isAspect(beanType)) {
                        // 3.1 有注解,开始处理
                        aspectNames.add(beanName);
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            MetadataAwareAspectInstanceFactory factory =
                                new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            // 3.2 开始封装advisors!这里getAdvisors和getBean的操作差不多
                            // 都是找不到就去创建
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            if (this.beanFactory.isSingleton(beanName)) {
                                // 3.3 加入advisorsCache缓存
                                this.advisorsCache.put(beanName, classAdvisors);
                            }
                            else {
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            advisors.addAll(classAdvisors);
                        }
                        else {
                            MetadataAwareAspectInstanceFactory factory =
                                new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                            this.aspectFactoryCache.put(beanName, factory);
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));
                        }
                    }
                }
                // 4. 记录所有切面类的名字
                this.aspectBeanNames = aspectNames;
                // 5. 返回所有的advisors
                return advisors;
            }
        }
    }

    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    List<Advisor> advisors = new ArrayList<>();
    for (String aspectName : aspectNames) {
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        }
        else {
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    return advisors;
}

getAdvisors()方法,在指定切面类上获取它的所有Advisors

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 1. 获取切面类的名字
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    validate(aspectClass);

    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
        new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 2. 【重要方法!】 遍历切面类的方法,判断上面有没有注解,封装**Advisor**
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }
    return advisors;
}

**getAdvisor()**方法,真正的去封装Advisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {

    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    // 1. 获取切点表达式!然后去匹配方法咯~
    AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }
    // 2. 实例化Advisor,Advisor的组成是 {切点、方法、切面名字...}
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

总结

AOP到底是怎么实现的?

  1. 首先AOP是通过**@EnableAspectJAutoProxy注解来开启AOP的,如果跟进这个注解会发现,注解上有@Import(AspectJAutoProxyRegistrar.class),它导入了一个AspectJAutoProxyRegistrar的类,由于这个类实现了ImportBeanDefinitionRegistrar**接口;当配置类被ConfigurationClassPostProcessor解析的时候,它会执行这个接口下的实现类方法,注册一个重要的类 AnnotationAwareAspectJAutoProxyCreator

    @EnableAspectJAutoProxy -> @Import(AspectJAutoProxyRegistrar.class) -> 配置类解析 -> 执行方法 -> 注册AnnotationAwareAspectJAutoProxyCreator

  2. AnnotationAwareAspectJAutoProxyCreator这个类实现了BeanPostProcessor接口,所以在注册BeanPostProcessor的时候,会实例化该类,而实例化该类时,它实现了BeanFactoryAware接口,所以在执行初始化方法前,它会执行Aware接口下的一个回调方法,通过这个方法,他实例化了一个重要的类BeanFactoryAspectJAdvisorsBuilderAdapter

    AnnotationAwareAspectJAutoProxyCreator -> 实现BeanPostProcessor -> 在regist的时候实例化 -> 实现BeanFactoryAware -> 初始化回调方法 -> 实例化BeanFactoryAspectJAdvisorsBuilderAdapter

  3. AOP重要的是通知(Advice)和切点(PointCut),什么时候封装他们的呢?在剩余的普通Bean的第一次createBean的时候,会调用resolveBeforeInstantiation()方法 给AOP一个机会去封装Advisor。而AOP会去调用BeanFactoryAspectJAdvisorsBuilderAdapter这个建造者去建造Advisors,建造者会扫描所有bean,找到Aspect切面类,然后进行方法遍历,封装每一个Advice+PointCut => Advisors;最后返回一个所有拥有的Advisors列表

    createBean -> resolveBeforeInstantiation() -> 调用builder -> 扫描所有bean -> 切面类 -> 扫描所有方法 -> 封装Advisor -> 汇总为Advisors


至此,AOP实例完成!接下来要做的就是在bean初始化之后或者实例化之后判断是否要进行AOP,如果要,给他动态代理就好!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值