Spring AOP AspectJ注解 源码笔记

作者: 丶含光 | 来源:发表于2019-08-18 18:50 被阅读0次

    简单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<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
            ...
            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            ...
            invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
            ...
    

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

        private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> 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<ConfigurationClass> 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<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
            for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> 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<Advisor> candidateAdvisors = findCandidateAdvisors();
            ...
        }
    
        protected List<Advisor> findCandidateAdvisors() {
            // Add all the Spring advisors found according to superclass rules.
            List<Advisor> 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<Advisor> buildAspectJAdvisors() {
                        ...
                        for (String beanName : beanNames) {
                            ...
                            if (this.advisorFactory.isAspect(beanType)) {
                                    ...
                                    List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
    

    AbstractAspectJAdvisorFactory中的isAspect方法

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

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

        public List<Advisor> 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<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        }
    
        protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
            ...
            List<Advisor> candidateAdvisors = findCandidateAdvisors();
            List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        }
    
        protected List<Advisor> findAdvisorsThatCanApply(
                List<Advisor> 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注解 源码笔记

        本文链接:https://www.haomeiwen.com/subject/zgsrsctx.html