Spring注解开发-查询手册及源码分析 置顶!
注册组件
@Configuration
@Configuration等于一个配置文件,如果某个Java类上标注了这个注解,则表示这个类是一个配置类。
@Bean
将一个Java类装配到Spring的IOC容器中,默认是singleton。id默认是方法名。
@Data
@AllConstructorArgs
@ToString
public class Person(){
private String name;
private Integer age;
}
@Configuration
public class MainConfig{
@Bean
public Person persion(){
return new Person("laowang",25);
}
}
测试:
public class Test1{
@Test
public void test1(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
}
}
@ComponentScan
在配置类上进行标注,指定Spring的扫描规则。
@Configuration
@ComponentScan(value="com.laowang.xxx")//使用某个包路径来指定Spring组件的扫描路径,如果想要装配的Bean不在这个指定的路径下,则不会被扫描。
public class MainConfig{
@Bean
public Person persion(){
return new Person("laowang",25);
}
}
excludeFilters排除
指定按照某些规则来排除组件。
使用TpyeFilter指定过滤规则
@Filter的FilterType
- FilterType.ANNOTATION 按注解排除
@Configuration
@ComponentScan(value="com.laowang.xxx",excludeFilters={
@Filter(type=FilterType.ANNOTATION,
classes={Controller.class})//排除Controller注解
})
public class MainConfig{
@Bean
public Person persion(){
return new Person("laowang",25);
}
}
- FilterType.ASPECTJ 按AspectJ表达式排除
- FilterType.ASSIGNABLE_TYPE 按类排除
@Configuration
@ComponentScan(value="com.laowang.xxx",excludeFilters={
@Filter(type=FilterType.ASSIGNABLE_TYPE,
classes={Controller.class})//排除Controller注解
})
public class MainConfig{
@Bean
public Person persion(){
return new Person("laowang",25);
}
}
- FilterType.CUSTOM 按自定义规则排除:需要创建一个类并实现TypeFilter接口
public class MyTypeFilter implememts TypeFilter{
/**
* metadataReader读取当前扫描类的信息
* metadataReaderFactory可以获取他类的任何信息
**/
@Override
public boolean match(MetadataReader metadataReader,MetadataReaderFactory metadataReaderFactory){
//获取当前类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类的资源信息(类路径等)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->" + className);//返回类的全路径名
if(className.contains("er")){//如果含有er,则装配
return true;
}
return false;
}
}
}
@Configuration
@ComponentScan(value="com.laowang.xxx",excludeFilters={
@Filter(type=FilterType.CUSTOM,
classes={MyTypeFilter.class})//使用自定义规则的Filter
})
public class MainConfig{
@Bean
public Person persion(){
return new Person("laowang",25);
}
}
- FilterType.REGEX 按正则排除
includeFilters包含
与excludeFilters相反,指定需要哪些组件要被包含扫描。但是要配合userDefaultFilters=false配合使用,因为默认的扫描规则是扫描所有的,如果不配置,则会使用默认的规则进行扫描。
@Configuration
@ComponentScan(value="com.laowang.xxx",includeFilters={
@Filter(type=FilterType.ANNOTATION,
classes={Controller.class})},//包含Controller注解
userDefaultFilters=false//禁用默认的扫描规则
)
public class MainConfig{
@Bean
public Person persion(){
return new Person("laowang",25);
}
}
@ComponentScans
在jdk8以后,@ComponentScan是个可重复注解@Repeatable。也可以使用@ComponentScans指定扫描策略
@ComponentScans({
ComponentScan(value="com.laowang.xxx",includeFilters={
@Filter(type=FilterType.ANNOTATION,
classes={Controller.class})},
userDefaultFilters=false)
})
@Scope
设置组件的作用域,如果是单例,则该Bean在装配的时候,Spring会自动创建并放到IOC容器中。如果是多实例,只会在使用到该Bean的时候才创建然后装配。
- singleton 单例(默认)
@Scope
- prototype 多实例
@Scope("prototype")
- request 在web环境中,可以设置为request
- session 在web环境中,可以设置为session
@Lazy-bean
针对singleton的实例,容器启动的时候先不创建,在第一次使用的时候创建,以后每次都从容器中去取。
@Conditional
按照条件注册Bean。
@Configuration
public class MainConfig{
//如果是windows系统,则注册bill,如果是linux则注册linus
@Condition({WindowsCondition.class})
@Bean("bill")
public Person person1(){
return new Person("Bill",50);
}
@Condition({LinuxCondition.class})
@Bean("linus")
public Person person2(){
return new Person("linus",48);
}
}
public class LinuxCondition implements Condition{
/**
* context:判断条件能使用的上下文
* annotatedTypeMetadata:注释信息
**/
@Override
public boolean matches(ConditionContext context,AnnotatedTypeMetadata annotatedTypeMetadata){
//判断是否是Linux系统
//能获取到ioc使用的beanFactory
ConfigurableListableBeanFactory factory = context.getBeanFactory();
//获取类加载信息
ClassLoader classLoader = context.getClassLoader();
//获取当前信息环境
Environment environment = context.getEnvironment();
//获取到Bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
String property = environment.getProperty("os.name");
if(property.contains("linux")){
return true;
}
return false;
}
}
public class WindowsCondition implements Condition{
@Override
public boolean matches(ConditionContext context,AnnotatedTypeMetadata annotatedTypeMetadata){
//获取当前信息环境
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("windows 10")){
return true;
}
return false;
}
}
<font style="color:red">备注:可以在运行的时候加参数:-Dos.name=linux进行测试。</font>
@Import
快速给容器导入组件,组件名默认为全类名
public class Color{}
@Cofiguration
@Import({Color.class,xxx.class})
public class MainConfig{
}
ImportSelector
导入选择器,需要自定义类并实现这个接口。
public calss Green{}
public class Blue{}
public class MyImportSelector implements ImportSelector{
//返回值就是要导入到组件中的类的全类名
//annotationMetadata:当前标注@Import注解类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata){
//方法不要返回null
return new String[]{"xxx.xxx.Green","xxx.xxx.Blue"};
}
}
@Cofiguration
@Import({Color.class,xxx.class,MyImportSelector.class})
public class MainConfig{
}
ImportBeanDefinitionRegistry
给容器中添加组件。
public class Rainbow{
}
public class MyImportBeanDefinitionRegistry implements ImportBeanDefinitionRegistry{
//把所有需要添加到容器中的Bean,可以通过BeanDefinitionRegistry.registerBeanDefinition注册进来。
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,BeanDefinitionRegistry registry){
boolean definition = registry.containsBeanDefinition("xxx.xxx.Green");
if(definition){
RootBeanDefinition beanDefinition = new RootBeanDefinition(Rainbow.class);
registry.registerBeanDefinition("rainbow",beanDefinition);
}
}
}
@Cofiguration
@Import({Color.class,xxx.class,MyImportSelector.class,MyImportBeanDefinitionRegistry.class})
public class MainConfig{
}
FactoryBean
工厂Bean,使用getObject()方法来注册Bean。
public class ColorFactoryBean implements FactoryBean<Color>{
//返回的对象会添加到容器中
@Override
public Color getObject() throws Exception{
return new Color();
}
//设置返回对象的类型
@Override
public Class<?> getObjectType(){
return Color.class;
}
//控制Bean是否是单例
@Override
public boolean isSingleton(){
return false;
}
}
@Cofiguration
public class MainConfig{
@Bean
ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
//注意,IOC容器会将ColorFactoryBean和Color同时注册。但是使用applicationContext.getBean("ColorFactoryBean");打印的结果是xxx.xxx.Color。因为这个装配的Bean实际是装配了Color这个类,而不是ColorFactoryBean这个类。
//而如果想要获取到这个ColorFactoryBean类的信息,则在获取Bean的时候加上&符号,即applicationContext.getBean("&ColorFactoryBean");打印的结果才是colorFactoryBean。
}
}
生命周期
@Bean指定初始化和销毁方法
Bean的生命周期:创建---初始化---销毁的过程。可以自定义初始化和销毁方法。
- 初始化:在对象完成,并赋值后,调用初始化方法。
- 销毁:在容器关闭的时候销毁。
- 单实例Bean会自动初始化和销毁,但是一旦该Bean被装配为多实例,在实际调用的时候才创建该Bean并且容器关闭的时候不会销毁该Bean,需要我们手动销毁。也就是说,在该Bean被装配为多实例后,容器只会帮忙创建而将不再管理该Bean。
指定init和detroy方法
public class Car {
public Car(){
System.out.println("car constructor....");
}
public void init(){
System.out.println("car init....");
}
public void destory(){
System.out.println("car destroy....");
}
}
@Configuration
public class MainConfig{
@Bean(initMethod="init",destroyMethod="destroy")
public Car car(){
return new Car();
}
}
注意:如果想要看到Bean销毁的效果,需要手动调用applcationContext.close()方法。
InitializingBean和DisposableBean
@Compoent
public class Trunk implements InitializingBean,DisposableBean {
public Trunk(){
System.out.println("trunk constructor....");
}
@Override
public void destory() throws Exception{
System.out.println("trunk destory....");
}
@Override
public void afterPropertiesSet() throws Exception{
System.out.println("trunk afterPropertiesSet....");
}
}
@PostConstruct和@PreDestroy
JSR250的规范。
@Component
public class Car {
public Car(){
System.out.println("car constructor....");
}
@PostConstruct
public void init(){
System.out.println("car init....");
}
@PreDestroy
public void destory(){
System.out.println("car destroy....");
}
}
BeanPostProcessor接口
在Bean初始化前后做一些事情,具体需要实现postProcessorBeforeInitialization和postProcessorAfterInitialization方法。
public class MyBeanPostProcessor implements BeanPostProcessor{
/**
* 可以返回origin bean 也可以返回wrapper bean
**/
@Override
public Object postProcessorBeforeInitialization(Object bean,String beanName) throws Exception{
System.out.println("postProcessorBeforeInitialization...");
return bean;
}
@Override
public Object postProcessorAfterInitialization(Object bean,String beanName) throws Exception{
System.out.println("postProcessorAfterInitialization...");
return bean;
}
}
属性赋值
@Value
- 可以写基本值
- 可以写SpEL表达式:#{}
- 可以写${}取出配置文件的值
@PropertySource
指定配置文件。
@PropertySource(value={"classpath:/xxx.properties"})
自动装配
@Autowired&@Qualifier&@Primary
- @Autowired默认按类型查找,如果找到多个相同类型的组件,再将属性名作为id查找。可以设置required=false,非必须。
- @Autowired如果放到构造器上,则传入的对象是从容器中获取。如果只有一个有参的构造函数,@Autowired可以省略。
- @Qualifier 明确指定要装配的组件id
- @Primary Spring自动装配的时候默认使用首选的Bean。
@Resource&@Inject
- JSR 250 @Resource,默认按名称进行装配。
- JSR 330 @Inject,需要引入javax.inject包,与@Autowired功能一样。
@Profile
Spring提供的可以根据当前环境动态激活和切换一系列组件(Bean)的功能。指定组件在哪个环境下才能被注册到容器。不指定的话,任何环境都能注册。
放在组件上
参数:value表示条件,默认值是default,比如:
@Profile("test")
@Bean("testDB")
xxx
@Profile("dev")
@Bean("devDB")
xxx
@Profile("prod")
@Bean("prodDB")
xxx
- 开发环境
- 测试环境
- 生产环境
放在类上
如果该注解放在类上,则这个类里面所有的组件都只有这个环境下才能会被注册。
使用
- 可以在运行时增加参数:-Dspring.profiles.active=test来调用相应的环境。
- 使用代码的方式
1、创建一个ApplicationContext对象:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
2、设置需要激活的环境,可以设置多个。
applicationContext.getEnvironment().setActiveProfiles("test","dev");
3、注册主配置类
applicationContext.register(MainConfig.class);
4、启动刷新容器
applicationContext.refresh();
Aware接口
BeanNameAware
组件名解析器
ApplicationContextAware
可注入Spring容器上下文。
EmbeddedValueResolverAware
值解析器
等等,如下图所示:
xxxProcessor
用来处理各种Aware注入的问题,以ApplicationContextAwareProcessor为例,底层源码如下:
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
//此处的作用是在Bean初始化之前做一些事情。
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
//判断该Bean是否是实现了xxxAware接口。
if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
//判断是否有权限
if (acc != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareInterfaces(bean);
return null;
}, acc);
//然后调用设置Aware的方法。
} else {
this.invokeAwareInterfaces(bean);
}
return bean;
}
//实际实现:判断具体是哪个Aware,最终将相应的Aware赋值给该bean的setXxxAware的方法。
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware)bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
}
//后置处理做一些事情。
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
AOP
概念
面向切面编程,需要增加功能的时候,不在源代码上进行修改,减少代码的耦合。使用面向切面的方式来对要执行的代码的前后逻辑进行控制。
- @Before前置通知
- @After后置通知
- @AfterReturning返回通知
- @AfterThrowing异常通知
- @Around环绕通知:动态代理,手动推进方法执行(joinPoint.procceed())。
例:
//注意,必须开启这个注解,表示启用注解版的切面功能。
@EnableAspectJAutoProxy
@Configuration
public class MainConfig{
@Bean
public Compute compute(){
return new Compute();
}
@Bean
public LogAspect logAspect(){
return new logAspect();
}
}
public class Compute {
public int div(int i,int j){
return i/j;
}
}
//告诉Spring当前类是个切面类。
@Aspect
public class LogAspect{
//也可以在此处创建一个方法,并且下面注解中的参数就填这个方法名。并且带上@PointCut。
@PointCut("execution()")
public void pointCut(){
}
@Before(切入表达式||"pointCut()")
public void logStart(){
System.out.println("logStart...");
}
@After(切入表达式)
public void logEnd(){
System.out.println("logEnd...");
}
//可以获取返回值
@AfterReturning(value=切入表达式,returning="result")
public void logReturn(Object result){
System.out.println("logReturn...");
}
//可以获取异常信息
@AfterThrowing(value=切入表达式, throwing="exception")
public void logExeption(JoinPoint joinPoint,Exception exception){
//可以通过这个参数获取方法的名称、参数等信息。
//获取方法名
joinPoint.getSignature().getName();
//获取参数。
joinPoint.getArgs();
System.out.println("logExeption...");
}
}
注意:JoinPoint一定要写在参数第一个。也就是:JoinPoint joinPoint,Exception exception。而不能写到后面:Exception exception,JoinPoint joinPoint,否则会报错。
切面表达式
execution (* com.sample.service.impl..*.*(..))
- execution(): 表达式主体。
- 第一个*号:表示返回类型,*号表示所有的类型。
- 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
- 第二个*号:表示类名,*号表示所有的类。
- *(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
源码分析
@EnableAspectJAutoProxy
这个注解调用了@Import(AspectJAutoProxyRegistrar.class):AspectJAutoProxyRegistrar可以给容器中导入自定义组件。实际上是注册了internalAutoProxyCreator这个组件。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
AspectJAutoProxyRegistrar() {
}
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//如果有需要就注册AspectJAnnotationAutoProxyCreator。
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
------------------------->
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
//调用注册方法
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
//注册或升级AnnotationAwareAspectJAutoProxyCreator
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
-------------------------->
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//判断是否已经有这个组件。
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
} else {
//否则就从RootBeanDefinition去注册一个AnnotationAwareAspectJAutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
//再注册internalAutoProxyCreator这个组件。
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
-> AspectJAwareAdvisorAutoProxyCreator
-> AbstractAdvisorAutoProxyCreator
-> AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor,BeanFactoryAware
后置处理器(在Bean初始化前后做一些事情)
- AbstractAutoProxyCreator.setBeanFatory()方法。
- AbstractAutoProxyCreator也有后置处理器的逻辑。
- AbstractAdvisorAutoProxyCreator重写了setBeanFatory()方法,也就是说实际是调用了子类的setBeanFatory()方法。
- AbstractAdvisorAutoProxyCreator.setBeanFatory() -> initBeanFactory();
- AnnotationAwareAspectJAutoProxyCreator重写了initBeanFactory()方法。
分析容器启动加载这些组件的流程
- 创建IOC容器:调用AnnotationConfigApplicationContext的有参构造函数。
//使用配置类的方式创建Spring容器
public AnnotationConfigApplicationContext(Class... annotatedClasses) {
//无参的构造器创建对象
this();
//注册配置类
this.register(annotatedClasses);
//刷新容器
this.refresh();
}
//使用包扫描路径的方式创建Spring容器。
public AnnotationConfigApplicationContext(String... basePackages) {
//无参的构造器创建对象
this();
//扫描包
this.scan(basePackages);
//刷新容器
this.refresh();
}
- refresh()方法:刷新容器,创建所有的Bean及初始化信息。
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册Bean的后置处理器,拦截Bean的创建。
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
- registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)方法,
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
- 先获取IOC容器中已经定义了的需要创建对象的所有BeanPostProcessor。
- 给容器中添加其他的BeanPostProcessor。
- 判断是否是实现了PriorityOrdered的类,如果是,就表示该类有优先加载的权限。
- 再注册是否实现了Ordered接口的类。
- 最后注册普通优先级的类。
- 从IOC容器中尝试获取BeanPostProcessor,如果没有,则创建。
- populateBean:给Bean的各种属性赋值。
- initializeBean:初始化Bean。
- invokeAwareMethods:处理Aware接口的方法回调。
- applyBeanPostProcessorBeforeInitialization():应用后置处理器在初始化之前的操作。
- invokeInitMethods():执行初始化方法。
- applyBeanPostProcessorAfterInitialization()::应用后置处理器在初始化之后的操作。
- BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功
aspectJAdvisorsBuilder
- 把BeanPostProcessor注册到BeanFactory中
beanFactory.addBeanPostProcessor(postProcessor);
- finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作
- 创建剩下的单实例bean。
- 遍历获取容器中所有的Bean:依次创建对象getBean(beanName)(getBean->doGetBean()->getSingleton())
- 创建bean:AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostProcessor,会调用postProcessBeforeInstantiation()。
- 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;只要创建好的Bean都会被缓存起来。
- createBean();创建bean;AnnotationAwareAspectJAutoProxyCreator 会在任何bean创建之前先尝试返回bean的实例
- BeanPostProcessor是在Bean对象创建完成初始化前后调用的
- InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的】
- resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation
希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续 - 后置处理器先尝试返回对象; bean = applyBeanPostProcessorsBeforeInstantiation():拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor;就执行postProcessBeforeInstantiation。
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
- doCreateBean(beanName, mbdToUse, args);真正的去创建一个bean实例。
AnnotationAwareAspectJAutoProxyCreator的作用
-
每一个bean创建之前,调用postProcessBeforeInstantiation();
- 关心MathCalculator和LogAspect的创建
- 判断当前bean是否在advisedBeans中(保存了所有需要增强bean)
- 判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)
- 是否需要跳过。
- 获取候选的增强器(切面里面的通知方法)【List
candidateAdvisors】每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor;判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;返回true。 - 永远返回false
-
创建对象postProcessAfterInitialization;
return wrapIfNecessary(bean, beanName, cacheKey);//包装如果需要的情况下- 获取当前bean的所有增强器(通知方法) Object[] specificInterceptors
- 找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)
- 获取到能在bean使用的增强器。
- 给增强器排序
- 保存当前bean在advisedBeans中;
- 如果当前bean需要增强,创建当前bean的代理对象;
- 获取所有增强器(通知方法)
- 保存到proxyFactory
- 创建代理对象:Spring自动决定
- JdkDynamicAopProxy(config);jdk动态代理;
- ObjenesisCglibAopProxy(config);cglib的动态代理;
- 给容器中返回当前组件使用cglib增强了的代理对象;
- 以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;
-
目标方法执行:容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存详细信息(比如增强器,目标对象,xxx)。
- CglibAopProxy.intercept();拦截目标方法的执行
- 根据ProxyFactory对象获取将要执行的目标方法拦截器链;
List
标题:Spring注解开发-查询手册及源码分析
作者:阿淼
地址:https://www.mmzsblog.cn/articles/2019/08/07/1565162136695.html
如未加特殊说明,文章均为原创,转载必须注明出处。均采用CC BY-SA 4.0 协议!
本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。若本站转载文章遗漏了原文链接,请及时告知,我们将做删除处理!文章观点不代表本网站立场,如需处理请联系首页客服。• 网站转载须在文章起始位置标注作者及原文连接,否则保留追究法律责任的权利。
• 公众号转载请联系网站首页的微信号申请白名单!