Spring AOP AspectJ注解 源码笔记

简单demo:

github
自定义切面MyAspect

@Aspect
@Component
@EnableAspectJAutoProxy
public class MyAspect {

    @Pointcut(value = "execution(* com.tianwen.spring.service..*.*d1(..))")
    public void pointcut() {}

    @Around(value = "pointcut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("before...");
        proceedingJoinPoint.proceed();
        System.out.println("after...");
    }

接口TestServiceI

public interface TestServiceI {

    void method1();

    void method2();
}

实现类TestServiceA

@Service
public class TestServiceA implements TestServiceI {

    @Override
    public void method1() {
        System.out.println("TestServiceA method1...");
    }

    @Override
    public void method2() {
        System.out.println("TestServiceA method2...");
    }
}

另一个没有实现接口的ServiceTestServiceB

@Service
public class TestServiceB {
    public void method1() {
        System.out.println("TestServiceB method1...");
    }
}

运行测试类Aop

public class Aop {

    @Test
    public void test1() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.tianwen.spring");
        TestServiceI testServiceI = (TestServiceI) context.getBean("testServiceA");
        testServiceI.method1();
        System.out.println("---");
        testServiceI.method2();
        System.out.println("---");
        TestServiceB testServiceB = (TestServiceB) context.getBean("testServiceB");
        testServiceB.method1();
    }
}

运行结果

before...
TestServiceA method1...
after...
---
TestServiceA method2...
---
before...
TestServiceB method1...
after...

分析:

@EnableAspectJAutoProxy
此注解不一定要在MyAspect这个类上,标注在任何一个可以被容器扫描到的类上即可,例如标注在TestServiceB上。

  1. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.tianwen.spring");
    public AnnotationConfigApplicationContext(String... basePackages) {
        this();
        scan(basePackages);
        refresh();
    }

    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

在无参构造器中,new AnnotatedBeanDefinitionReader()

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)有向容器注册ConfigurationClassPostProcessor类,这是一个BeanFactoryPostProcessor,在容器创建过程中会被调用。

        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
  1. AnnotationConfigApplicationContext构造器中调用的refresh()方法,实为AbstractApplicationContextrefresh()方法。
    public void refresh() throws BeansException, IllegalStateException {
        ...
        invokeBeanFactoryPostProcessors(beanFactory);
        ...
    }

关注refresh()中的invokeBeanFactoryPostProcessors(),其目的是为了执行所有的BeanFactoryPostProcessor

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

委派类PostProcessorRegistrationDelegateinvokeBeanFactoryPostProcessors方法。
先根据类型获取到所有的BeanDefinitionRegistryPostProcessor,获取到了1中向容器注册的ConfigurationClassPostProcessor类,因为其实现了接口PriorityOrdered,优先执行。

    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
        ...
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        ...
        invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
        ...

invokeBeanDefinitionRegistryPostProcessors方法中执行这些postProcessorpostProcessBeanDefinitionRegistry方法。

    private static void invokeBeanDefinitionRegistryPostProcessors(Collection postProcessors, BeanDefinitionRegistry registry) {

        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }
  1. ConfigurationClassPostProcessor用来处理所有扫描到的配置类,其postProcessBeanDefinitionRegistry
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        }
        if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanFactory already called on this post-processor against " + registry);
        }
        this.registriesPostProcessed.add(registryId);

        processConfigBeanDefinitions(registry);
    }

关注processConfigBeanDefinitions方法。在处理扫描到的配置类时(配置类分为完全配置类和不完全配置类,都会在这个过程中处理)

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
...
            this.reader.loadBeanDefinitions(configClasses);
}

loadBeanDefinitionsForConfigurationClass方法

    public void loadBeanDefinitions(Set configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        for (ConfigurationClass configClass : configurationModel) {
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }

loadBeanDefinitionsForConfigurationClass,在处理到MyAspect时,获取到类上标注的注解@EnableAspectJAutoProxy,该注解内有@Import(AspectJAutoProxyRegistrar.class)AspectJAutoProxyRegistrar是一个ImportBeanDefinitionRegistrar

    private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
            TrackedConditionEvaluator trackedConditionEvaluator) {
        ...
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }

loadBeanDefinitionsFromRegistrars调用对应的registerBeanDefinitions方法,即类AspectJAutoProxyRegistrarregisterBeanDefinitions方法。

    private void loadBeanDefinitionsFromRegistrars(Map registrars) {
        for (Map.Entry entry : registrars.entrySet()) {
            entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
        }
    }

AspectJAutoProxyRegistrarregisterBeanDefinitions方法中向容器注册AnnotationAwareAspectJAutoProxyCreator,这是一个BeanPostProcessor(注意区分BeanFactoryPostProcessorBeanPostProcessor

    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
  1. 回到refresh()方法中看finishBeanFactoryInitialization()
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        ...
        beanFactory.preInstantiateSingletons();
    }

DefaultListableBeanFactorypreInstantiateSingletons()方法中,会对需要被创建的bean进行创建。

    public void preInstantiateSingletons() throws BeansException {
            ...
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    ...
                    getBean(beanName);
            }

这是一个容器创建bean的过程,
getBean->doGetBean->createBean
AbstractAutowireCapableBeanFactorycreateBean方法中,尝试返回代理类。

    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
            ...
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

AbstractAutowireCapableBeanFactoryresolveBeforeInstantiation方法

    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
                    ...
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);

        ...
        return bean;
    }

applyBeanPostProcessorsBeforeInstantiation中执行所有的InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation方法

    protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

因为InstantiationAwareBeanPostProcessorAnnotationAwareAspectJAutoProxyCreator的基类:
所以这里会执行上述向容器注册的AnnotationAwareAspectJAutoProxyCreatorpostProcessBeforeInstantiation方法,实际调用基类AbstractAutoProxyCreator的对应方法

    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
            ...
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
            ...
    }

shouldSkip方法中,获取合适的通知器。

    protected boolean shouldSkip(Class beanClass, String beanName) {
        List candidateAdvisors = findCandidateAdvisors();
        ...
    }

    protected List findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        List advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }

BeanFactoryAspectJAdvisorsBuilderbuildAspectJAdvisors中,取得所有的beanName,使用isAspect方法判断其是否属于切面,取得通知器。

    public List buildAspectJAdvisors() {
                    ...
                    for (String beanName : beanNames) {
                        ...
                        if (this.advisorFactory.isAspect(beanType)) {
                                ...
                                List classAdvisors = this.advisorFactory.getAdvisors(factory);

AbstractAspectJAdvisorFactory中的isAspect方法

    @Override
    public boolean isAspect(Class clazz) {
        return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
    }

ReflectiveAspectJAdvisorFactory中的getAdvisors方法。取得切面上的切点与通知器。通知器类型为InstantiationModelAwarePointcutAdvisorImpl

    public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
            ...
            Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
    }

    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {
        ...
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        ...
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);

    }

此时,自定义的MyAspect上的@Aspect注解生效,被判断为一个通知器,加入到通知器List中。
再回到容器创建bean的过程中,在AbstractAutowireCapableBeanFactory createBean方法,doCreateBean方法,initializeBean方法,applyBeanPostProcessorsAfterInitialization方法。执行BeanPostProcessor的后置方法。

    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        ...
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    }

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {
                ...
                exposedObject = initializeBean(beanName, exposedObject, mbd);
    }

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
            ...
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

所以这里会执行上述向容器注册的AnnotationAwareAspectJAutoProxyCreator的的postProcessAfterInitialization方法,实际调用基类AbstractAutoProxyCreator的对应方法

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                ...
                return wrapIfNecessary(bean, beanName, cacheKey);
    }

wrapIfNecessary方法中,getAdvicesAndAdvisorsForBeanfindEligibleAdvisors内取得合适的通知器。判断这些通知器是否适用当前bean。

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        ...
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    }

    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
        ...
        List advisors = findEligibleAdvisors(beanClass, beanName);
    }

    protected List findEligibleAdvisors(Class beanClass, String beanName) {
        ...
        List candidateAdvisors = findCandidateAdvisors();
        List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    }

    protected List findAdvisorsThatCanApply(
            List candidateAdvisors, Class beanClass, String beanName) {
            ...
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }

最终在AopUtilsfindAdvisorsThatCanApplycanApply方法中,获取到切点(AspectJExpressionPointcut)的方法匹配器,对当前bean的方法逐个匹配,一旦匹配到,返回true。外层会返回对应的通知器,进而可得知需要为当前bean创建代理对象。是否需要为bean创建aop的代理对象,就是由此判断得知。

    public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {
        MethodMatcher methodMatcher = pc.getMethodMatcher();
            for (Method method : methods) {
                if ((introductionAwareMethodMatcher != null &&
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }

        return false;
    }

createProxy中使用ProxyFactory创建代理对象。

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        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;
        }

        // 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;
        }

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

而关于ProxyFactory如何创建代理对象,调用代理对象时,切面上的方法如何工作,与之前分析的ProxyFactoryBean流程大体一致。

总结:

  • 容器创建过程中,默认会向容器中注册ConfigurationClassPostProcessor类,一个BeanFactoryPostProcessor,以用来处理所有扫描到的配置类。
  • 容器创建过程中,在处理到被@EnableAspectJAutoProxy标注的类,解析该类注解时,对于@EnableAspectJAutoProxy上的@Import(AspectJAutoProxyRegistrar.class)的处理。会向容器中注册AnnotationAwareAspectJAutoProxyCreator,一个BeanPostProcessor。(注意区分BeanFactoryPostProcessorBeanPostProcessor
  • 容器完成创建后,会对不需要延迟注册的bean提前完成注册。
  • 在bean的创建过程中,在AbstractAutowireCapableBeanFactorycreateBeanresolveBeforeInstantiation方法中,执行beanPostProcessorpostProcessBeforeInstantiation方法时。上一步往容器中注册的AnnotationAwareAspectJAutoProxyCreator会工作,在执行其从基类AbstractAutoProxyCreator继承过来的postProcessBeforeInstantiation方法时,收集容器中所有的bean通知器。关于是否为通知器的判断方法在AbstractAspectJAdvisorFactoryisAspect方法中。
  • 在bean的创建过程中,在AbstractAutowireCapableBeanFactorydoCreateBeaninitializeBean方法中,执行所有beanPostProcessorpostProcessAfterInitialization方法。所以,AbstractAutoProxyCreatorpostProcessAfterInitialization方法会被执行,最终执行的是wrapIfNecessary方法。在该方法内,获取到配置的通知器,对每一个需要向容器注册的bean,用通知器上的切点的匹配规则对当前bean的方法逐个匹配,如果至少有一个方法匹配,说明需要创建代理对象,则使用ProxyFactory完成代理对象的创建(与之前分析的ProxyFactoryBean流程大体一致)。如果全部不匹配,返回普通bean。
  • 最终在方法调用时,如果是普通bean只是简单的方法调用,但如果是代理对象,方法调用过程中还伴随着织入的逻辑。至于这些逻辑如何工作。与之前分析的ProxyFactoryBean流程大体一致。
  • 目前看起来,上述方式的springAop配置,只是仅仅使用到了AspectJ的注解。

你可能感兴趣的:(Spring AOP AspectJ注解 源码笔记)