博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring系列之Spring框架和SpringAOP集成过程分析(十一)
阅读量:6902 次
发布时间:2019-06-27

本文共 13661 字,大约阅读时间需要 45 分钟。

我们在这篇文章中来分析一下AnnotationAwareAspectJAutoProxyCreator这个类,看这个类的名字我们大概可以知道它主要是为AspectJ注解提供服务的类。这个类不得了了是一个相当厉害的类,在这个类中可以识别应用中的所有切面类,为目标类找寻合适的Advisor,将目标类变为代理类等功能。话不多说了,下面我们来简单的分析一下这个类。

首先我们来看一下这个类的类图:
AnnotationAwareAspectJAutoProxyCreator
从上面的图中我们可以看到AnnotationAwareAspectJAutoProxyCreator这个类间接实现了BeanFactoryAware、BeanClassLoaderAware、Ordered、BeanPostProcessor接口。如果之前没有了解过Spring Bean的生命周期(或者是Spring开放的对Bean进行修改的扩展接口)的话,请点击这里查看( 和 )这里就不再多说了。上面提到的接口的实现类大多是在AbstractAutoProxyCreator这个类中实现的。Spring提供的这些关于Bean的扩展接口大大方便了我们在Bean的创建过程中对Bean进行一些修改的操作。我们按照顺序来看看AnnotationAwareAspectJAutoProxyCreator这个关系链上对这些接口的实现。

AbstractAdvisorAutoProxyCreator#setBeanFactory

@Override    public void setBeanFactory(BeanFactory beanFactory) {        //掉用父类的setBeanFactory 这里只是一个简单的赋值        super.setBeanFactory(beanFactory);        //如果BeanFactory不是ConfigurableListableBeanFactory类型的 抛出异常        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {            throw new IllegalArgumentException(                    "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);        }        //初始化BeanFactory        initBeanFactory((ConfigurableListableBeanFactory) beanFactory);    }    //这个方法在AnnotationAwareAspectJAutoProxyCreator这个类型中    @Override    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {        //调用父类的initBeanFactory 执行的内容如下:        //this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);        //创建BeanFactoryAdvisorRetrievalHelperAdapter 从BeanFactory中获取Advisor类型的Bean        super.initBeanFactory(beanFactory);        if (this.aspectJAdvisorFactory == null) {            //创建ReflectiveAspectJAdvisorFactory 相当重要的一个类            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);        }        //创建BeanFactoryAspectJAdvisorsBuilderAdapter 相当重要的一个类        //为目标类型创建对应的Advisor的类        this.aspectJAdvisorsBuilder =                new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);    }

AbstractAutoProxyCreator#postProcessBeforeInstantiation

这个方法可以让我们在Bean被Spring容器实例化之前提前创建Bean,如果这个方法返回的值不是null,那就中断其他类对这个接口的实现,直接返回这个创建的Bean。在AbstractAutoProxyCreator中其源码如下:

public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException { //得到一个缓存的key 实现是:如果是beanClass是FactoryBean类型,则在beanName前面加& Object cacheKey = getCacheKey(beanClass, beanName); //如果目标Bean的集合中包这个beanName的话 则跳过 if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } //isInfrastructureClass 判断是不是负责AOP基础建设的Bean,如果是AOP基础建设的Bean不能在这里被创建代理对象 //那么什么样的Bean是AOP的基础建设Bean呢?Advice、Pointcut、Advisor、AopInfrastructureBean类型的Bean //以及含有Aspect注解的Bean //shouldSkip这个方法是判断这个类型的Bean能不能被跳过,如果可以跳过,那么就不提前创建这个类 //这个类我们在下面详细分析 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { //缓存这个beanClass this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } / Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. if (beanName != null) { //一般我们都是不配置TargetSourceCreator 下面的步骤我们先跳过 在后面我们还会继续分析下面的内容的 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } }

AspectJAwareAdvisorAutoProxyCreator#shouldSkip

protected boolean shouldSkip(Class
beanClass, String beanName) { // TODO: Consider optimization by caching the list of the aspect names //我们重点看到是findCandidateAdvisors这个方法的内容 //查找所有可选择对的Advisor 并且或进行缓存 List
candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor) { //如果AbstractAspectJAdvice类型的Advice中有aspectName和beanName相等则跳过 if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) { return true; } } } //父类直接返回一个false return super.shouldSkip(beanClass, beanName); }
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override    protected List
findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 同样是先调用父类的findCandidateAdvisors List
advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. //构建所有切面Bean中的Advisor //很重要的一个方法 下面分析 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; } // AbstractAdvisorAutoProxyCreator#findCandidateAdvisors protected List
findCandidateAdvisors() { //这个advisorRetrievalHelper 就是我们在 initBeanFactory中创建的BeanFactoryAdvisorRetrievalHelper return this.advisorRetrievalHelper.findAdvisorBeans(); } // BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans //这个方法的内容是从Spring容器中获取Advisor类型的Bean public List
findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = null; synchronized (this) { //先看看之前是不是缓存过 advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! //上面的注释说的很清楚 这里不会初始化FactoryBean 为什么会这样说呢?因为提前导致FactoryBean类型的Bean被创建的话是会有问题的 //从BeanFactory中获取所有的Advisor类型的Bean advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); //这里进行赋值缓存 this.cachedAdvisorBeanNames = advisorNames; } } //如果没有Advisor类型的Bean的话 直接返回 //如果你有特殊需求的话 可以实现Advisor接口,并向Spring容器中注入对应的Bean if (advisorNames.length == 0) { return new LinkedList
(); } //这里是默认创建了一个 Advisor类型的集合 List
advisors = new LinkedList
(); for (String name : advisorNames) { //这里默认返回的是true if (isEligibleBean(name)) { //如果是正在创建中的Bean 则跳过 if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { //从BeanFactory中获取对应的Bean 这里如果Bean还没创建 会导致Bean创建 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { //异常处理 略 } } } } return advisors; }

下面我们来看看BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors中的这个方法,从名字我们就可以看出来这是一个从BeanFactory中构建Advisor的方法。

public List
buildAspectJAdvisors() { //所有的切面的名字 这里的处理逻辑和上面的是一样的 获取到所有的切面BeanName之后缓存起来 volatile类型的 List
aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { //这里又赋值了一次 看着这个逻辑是不是和某个单例的写法很像啊? aspectNames = this.aspectBeanNames; if (aspectNames == null) { List
advisors = new LinkedList
(); aspectNames = new LinkedList
(); //这里是从BeanFactory中获取所有的Bean String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { //这里默认都是true if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. //注意看上面这个注释的内容:在这个场景下我们获取BeanClass的时候必须要小心处理,以免会提前初始化 //Bean,这些Bean在初始化之后会被Spring容器缓存起来,但是这些Bean可能还没有被织入。 Class
beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } //判断上面获取到的BeanClass是否带有Aspect注解 if (this.advisorFactory.isAspect(beanType)) { //添加到 aspectNames中 aspectNames.add(beanName); //创建切面元数据 这部门的内容和我们之前分析大致差不多 我们就不再详细分析了 //请看这里: https://blog.csdn.net/zknxx/article/details/79685290 AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { //注意这里放入了 BeanFactory的引用 方便后面从BeanFactory中获取切面的实例 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List
classAdvisors = this.advisorFactory.getAdvisors(factory); //如果是单例的 缓存起来 if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } //这里使用的是 PrototypeAspectInstanceFactory MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } //下面这些就是从缓存中获取Advisor了 List
advisors = new LinkedList
(); for (String aspectName : aspectNames) { List
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; }

总结起来findCandidateAdvisors这个方法的内容就是从Spring容器中获取所有Advisor类型的Bean和切面中所有带有通知注解的方法并将其封装为Advisor。那么其实我们在AbstractAutoProxyCreator的postProcessBeforeInstantiation方法中就获取到了Spring容器中的所有Advisor。

AbstractAutoProxyCreator#postProcessAfterInstantiation
//通常都是返回true    @Override    public boolean postProcessAfterInstantiation(Object bean, String beanName) {        return true;    }

AbstractAutoProxyCreator#postProcessPropertyValues

@Override    public PropertyValues postProcessPropertyValues(            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {        //不做处理        return pvs;    }

AbstractAutoProxyCreator#postProcessBeforeInitialization

@Override    public Object postProcessBeforeInitialization(Object bean, String beanName) {        //不做处理原样返回        return bean;    }
AbstractAutoProxyCreator#postProcessAfterInitialization

这个方法需要重点分析一下了

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {          if (bean != null) {            //获取缓存的key            Object cacheKey = getCacheKey(bean.getClass(), beanName);            //如果不是提前引用的Bean            if (!this.earlyProxyReferences.contains(cacheKey)) {                //如果需要的话 对传入的Bean进行包装                return wrapIfNecessary(bean, beanName, cacheKey);            }        }        return bean;    }    //这个方法的主要作用就是创建代理对象    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {        //如果已经创建过了         if (beanName != null && this.targetSourcedBeans.contains(beanName)) {            return bean;        }        //如果这里返回的是False的话 直接返回        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {            return bean;        }        //这里又判断了一次不再多说了、、、        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {            this.advisedBeans.put(cacheKey, Boolean.FALSE);            return bean;        }        //getAdvicesAndAdvisorsForBean这个方法下面我们要重点说一下        // Create proxy if we have advice.        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);        if (specificInterceptors != DO_NOT_PROXY) {            this.advisedBeans.put(cacheKey, Boolean.TRUE);            //创建代理对象              Object proxy = createProxy(                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));            this.proxyTypes.put(cacheKey, proxy.getClass());            return proxy;        }        //如果不需要创建代理对象的话  这里缓存false        this.advisedBeans.put(cacheKey, Boolean.FALSE);        return bean;    }
你可能感兴趣的文章