赞
踩
加载beanDefinition有两种方式,一种是xml形式,一种是注解,xml形式通过Resource加载器加载,DOM解析,封装成BeanDefinition,注册到beanDefinitionMap;注解方式依赖于@ComponentScan注解,该注解上配置了包扫描路径,启动过程中,后置处理器ConfigurationClassPostProcessor调用了处理方法,创建ClassPathBeanDefinitionScanner,调用doScan方法,这里是@ComponentScan的实质性逻辑,从配置的包路径下获取所有的类,遍历出符合过滤条件的类,默认是带有@Component注解的,然后注册到beanDefinitionMap中
bean工厂后置处理器,spring的扩展点,可以自定义类实现BeanFactoryPostProcessor接口,该接口的实现方法中能拿到beanFactory,进而实现对beanFactory的修改定制。后置处理器的创建和调用在refresh()里面的invokeBeanFactoryPostProcessors(beanFactory)
bean后置处理器,spring的扩展点,可以自定义类实现BeanPostProcessor接口,该接口有两个实现方法,一个是初始化前,一个是初始化后,可以对bean进行修改。后置处理器的创建在refresh()里面的registerBeanPostProcessors(beanFactory),调用则是在finishBeanFactoryInitialization(beanFactory),即普通单例bean创建的过程中org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor
在bean初始化前后做一些事情
@EnableAspectJAutoProxy
开启aoppackage com.example.aop; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy public class AopApplication { public static void main(String[] args) { SpringApplication.run(AopApplication.class, args); } }
@Aspect
标注,定义切点,编写增强方法package com.example.aop.aspect; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class UserAspect { @Pointcut("execution(* com.example.aop.service..*(..))") public void pointcut(){} @Before("pointcut()") public void before(){ System.out.println("before.."); } }
@EnableAspectJAutoProxy --> @Import(AspectJAutoProxyRegistrar.class
)
AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
--> AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); --> return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class
, registry, source);
可以看到,引入了AnnotationAwareAspectJAutoProxyCreator,一个bean后置处理器
AbstractAutoProxyCreator
的父类实现了InstantiationAwareBeanPostProcessor
接口,在bean实例化before
方法里面实现了切面的解析逻辑
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
,这个方法遍历所有的beanName,从beanFactory拿到bean信息,判断有没有@Aspect
注解,有说明是切面,进行解析,将其转化成Advisor
解析完切面之后就是创建代理
了,创建代理发生在初始化After方法org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
获取bean的匹配的advisor,然后创建代理,配置了proxy-target-class="true"使用cglib,没有没有配置且有接口则使用jdk动态代理
https://blog.csdn.net/gongsenlin341/article/details/113281596
<import/>
元素等价的功能。@Configuration
配置类,ImportSelector
和ImportBeanDefinitionRegistrar
实现类,以及常规组件AnnotationConfigApplicationContext#register
)。强调一下,普通类的处理会被包装成配置类进行处理,ImportSelector里面的类经过递归也会调用普通类的处理方法
public interface ImportSelector { /** * Select and return the names of which class(es) should be imported based on * the {@link AnnotationMetadata} of the importing @{@link Configuration} class. * @return the class names, or an empty array if none * * 基于导入的配置类的注解元数据来选择并返回那些需要导入的类的名称 * 返回那些类名,如果没有则返回空数组 * 这个地方如果返回的是ImportSelector ,貌似会死循环哦 */ String[] selectImports(AnnotationMetadata importingClassMetadata); /** * Return a predicate for excluding classes from the import candidates, to be * transitively applied to all classes found through this selector's imports. * <p>If this predicate returns {@code true} for a given fully-qualified * class name, said class will not be considered as an imported configuration * class, bypassing class file loading as well as metadata introspection. * @return the filter predicate for fully-qualified candidate class names * of transitively imported configuration classes, or {@code null} if none * @since 5.2.4 * * 返回一个断言,用于从导入候选对象中排除类 */ @Nullable default Predicate<String> getExclusionFilter() { return null; } }
@Import(ImportSelector.class)相当于在@Import(普通类)的基础上做了增强,通过接口返回数组允许导入多个类,然后通过断言又可以对导入的类进行过滤
public interface ImportBeanDefinitionRegistrar { /** * Register bean definitions as necessary based on the given annotation metadata of * the importing {@code @Configuration} class. * * 根据需要基于导入的配置类的注解元数据注册bean 的定义 */ default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { registerBeanDefinitions(importingClassMetadata, registry); } /** * Register bean definitions as necessary based on the given annotation metadata of * the importing {@code @Configuration} class. */ default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { } }
@Import(ImportBeanDefinitionRegistrar .class)可以更灵活的注册BeanDefinition,因为ImportBeanDefinitionRegistrar 接口的两个方法参数可以直接拿到registry。但是此种方式的逻辑调用跟前两种有点差别,这是在所有的配置类(@Configuration修饰的和包装的配置类)解析成ConfigurationClass之后,执行配置类的加载bean定义方法里面执行的;而之前提到的两种配置类的解析过程中执行的。
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
https://blog.csdn.net/hc1428090104/article/details/124823573
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。