AOP源码解析(二)创建AOP代理

上文中讲解了通过自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator类型的自动注册,那么这个类到底做了什么工作来完成AOP的操作呢?首先我们看看AnnotationAwareAspectJAutoProxyCreator的层次结构
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator

这个类的父类的父类的父类实现了BeanPostProcessor接口,而实现BeanPostProcessor后,当Spring加载这个Bean时会在实例化前调用其postProcesssAfterIntialization方法,而我们对于AOP逻辑的分析也由此开始。

在父类AbstractAutoProxyCreator的postProcessAfterInitialization中代码如下:

    public Object postProcessAfterInitialization(Object bean, String beanName)
        throws BeansException
    {
        if(bean != null)
        {
            //根据给定的bean的class和name构建出个key,格式:beanClassName_beanName
           Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if(!earlyProxyReferences.containsKey(cacheKey))
               //如果它适合被代理,则需要封装指定bean
              return wrapIfNecessary(bean, beanName, cacheKey);
        }
        return bean;
    }
 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey)
    {
        //如果已经处理过
       if(beanName != null && targetSourcedBeans.containsKey(beanName))
            return bean;
        //无需增强
       if(Boolean.FALSE.equals(advisedBeans.get(cacheKey)))
            return bean;
        //给定的bean类是否代表一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要自动代理
       if(isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName))
        {
            advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
        //如果存在增强方法则创建代理
       Object specificInterceptors[] = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        //如果获取到了增强则需要针对增强创建代理
        if(specificInterceptors != DO_NOT_PROXY)
        {
            advisedBeans.put(cacheKey, Boolean.TRUE);
            //创建代理
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        } else
        {
            advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }
函数中我们已经看到了代理创建的雏形。当然,真正开始之前还需要经过一些判断,比如是否已经处理过或者是否是需要跳过的bean,而真正创建代理的代码是从getAdvicesAndAdvisorsForBean开始的。

创建代理主要包含了两个步骤:

(1)获取增强方法或者增强器;

(2)根据获取的增强进行代理。

其中逻辑复杂,我们首先来看看获取增强方法的实现逻辑。

    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource)
    {
        List advisors = findEligibleAdvisors(beanClass, beanName);
        if(advisors.isEmpty())
            return DO_NOT_PROXY;
        else
            return advisors.toArray();
    }

    protected List findEligibleAdvisors(Class beanClass, String beanName)
    {
        List candidateAdvisors = findCandidateAdvisors();
        List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if(!eligibleAdvisors.isEmpty())
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        return eligibleAdvisors;
    }

对于指定bean的增强方法的获取一定是包含两个步骤的,获取所有的增强以及寻找所有增强中使用于bean的增强并应用,那么findCandidateAdvisors与findAdvisorsThatCanApply便是做了这两件事情。当然,如果无法找到对应的增强器便返回DO_NOT_PROXY,其中DO_NOT_PROXY=null.

1.获取增强器

由于我们分析的是使用注解进行的AOP,所以对于findCandidateAdvisors的实现其实是由AnnotationAwareAspectJAutoProxyCreator类完成的,我们继续跟踪AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors方法。

    protected List findCandidateAdvisors()
    {
        //当使用注解方式配置AOP的时候并不是丢弃了对XML配置的支持。
        //在这里调用父类方法加载配置文件中的AOP声明
        List advisors = super.findCandidateAdvisors();
        //Build Advisors for all AspectJ aspects in the bean factory
        advisors.addAll(aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
 
AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAdvisorAutoProxyCreator,在实现获取增强的方法中除了保留父类的获取配置文件中定义的增强外,同时添加了获取Bean的注解增强的功能,那么其实现正是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()来实现的。

在真正研究代码之前读者可以尝试着自己去想象一下解析思路,看看自己的实现与Spring是否有差别呢?或者我们一改以往的方式,先来了解函数提供的大概功能框架,读者可以在头脑中尝试实现这些功能点,看看是否有思路。

(1)获取所有beanName,这一步骤中所有在beanFactory中注册的Bean都会被提取出来。

(2)遍历所有beanName,并找出声明AspectJ注解的类,进行进一步的处理。

(3)对标记为AspectJ注解的类进行增强器的提取。

(4)将提取结果加入缓存。

现在我们来看看函数实现,对Spirng中所有的类进行分析,提取Advisor。

public List buildAspectJAdvisors()
    {
        List aspectNames = null;
        synchronized(this){
        aspectNames = aspectBeanNames;
        if(aspectNames == null)
        {
            List advisors = new LinkedList();
            aspectNames = new LinkedList();
            //获取所有的beanName
            String beanNames[] = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, java/lang/Object, true, false);
            //循环所有的beanName找出对应的增强方法
            for(String beanName : beanNames)
            {
                //不合法的bean则略过,由子类定义规则,默认返回true
               if(!isEligibleBean(beanName))
                    continue;
                //获取对应的bean的类型
                Class beanType = beanFactory.getType(beanName);
                //如果存在Aspect注解
               if(beanType == null || !advisorFactory.isAspect(beanType))
                    continue;
                aspectNames.add(beanName);
                AspectMetadata amd = new AspectMetadata(beanType, beanName);
                MetadataAwareAspectInstanceFactory factory;
                if(amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON)
                {
                    factory = new BeanFactoryAspectInstanceFactory(beanFactory, beanName);
                    //解析标记AspectJ注解中的增强方法
                    List classAdvisors = advisorFactory.getAdvisors(factory);
                    if(beanFactory.isSingleton(beanName))
                        advisorsCache.put(beanName, classAdvisors);
                    else
                        aspectFactoryCache.put(beanName, factory);
                    advisors.addAll(classAdvisors);
                    continue;
                }
                if(beanFactory.isSingleton(beanName))
                    throw new IllegalArgumentException((new StringBuilder()).append("Bean with name '").append(beanName).append("' is a singleton, but aspect instantiation model is not singleton").toString());
                factory = new PrototypeAspectInstanceFactory(beanFactory, beanName);
                aspectFactoryCache.put(beanName, factory);
                advisors.addAll(advisorFactory.getAdvisors(factory));
            }

            aspectBeanNames = aspectNames;
            return advisors;
       
    }

至此,我们已经完成了Advisor的提取,在上面的步骤中最为重要也最为繁杂的就是增强器的获取,而这一切功能委托给了getAdvisors方法去实现(this.advisorFactory.getAdvisors(factory))。
    public List getAdvisors(MetadataAwareAspectInstanceFactory maaif)
    {
        //获取标记为AspectJ的类
        Class aspectClass = maaif.getAspectMetadata().getAspectClass();
        //获取标记为AspectJ的name
        String aspectName = maaif.getAspectMetadata().getAspectName();
        //验证
        validate(aspectClass);
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(maaif);
        List advisors = new LinkedList();
        ReflectionUtils.doWithMethods(aspectClass,ReflectionUtils,MethodCallback(){
            public void doWith(Method method) throws IllegalArgumentException{
                 //声明为Pointcut的方法不处理           
                 if(AnnotationUtils.getAnnotation(method,Pointcut.class)==null){<pre name="code" class="java">                      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
                      if(advisor != null)
                      advisors.add(advisor);

}
}
}); if(!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { //如果寻找的增强器不为空而且又配置了增强延迟初始化那么需要在首位加入同步实例化增强器
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } for(Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if(advisor != null) advisors.add(advisor); } return advisors; }

 函数中首先完成了增强器的获取,包括获取注解以及根据注解生成增强的步骤,然后考虑到在配置中可能会将增强配置成延迟初始化,那么需要在首位加入同步实例化增强器以保证增强使用之前的实例化,最后是对DeclareParents注解的获取,下一节我们一起分析每个步骤。 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值