文章目录
- 前言
- Spring相关代码
- pom.xml
- 配置文件beans.xml
- 实体类
- 测试类
- 一、创建BeanFactory
- ApplicationContext
- BeanFactory和ApplicationContext的区别
- 补充
- 如何从容器中获取对象?
- 二、读取xml等,将bean定义信息放入BeanDefinition
- 三、对BeanDefinition中的属性值进行替换
- 补充
- BeanFactoryPostProcessor.postProcessBeanFactory()
- BeanFactoryPostProcessor接口与BeanPostProcessor接口
- 四、Bean实例化
- 补充
- Spring Bean生命周期图
- AbstractAutowireCapableBeanFactory.createBeanInstance()
- 五、依赖注入
- 1.简单属性注入:
- 2.基于注解的属性赋值
- @Autowired注解
- @Value注解
- 六、Bean初始化
- Aware
- BeanPostProcessor 的前置处理
- 调用自定义初始化方法
- 补充
- 当执行完属性赋值步骤之后,对象的创建和属性的赋值都完成了,那么此时对象是否可以直接拿来使用了?
- 七、Bean 的后置处理
- 八、使用Bean
- 九、销毁Bean
- 总结
前言
本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。
主要内容为Spring的执行流程梳理,主线为Spring源码中bean创建到销毁的流程梳理和其中关键的接口,如:BeanFactory、BeanDefinition、PostProcessor等。
补充内容为扩展内容,跳过不影响理解。
Spring相关代码
pom.xml
java"><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.7</version>
</dependency>
配置文件beans.xml
放在resources目录下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.qf.entity.User"><property name="name" value="zhangsan"></property><property name="age" value="1"></property></bean>
</beans>
实体类
java">public class User {private Long id;private String name;private int age;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
测试类
java">import com.qf.entity.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author qf*/
public class MyTest {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");User user = (User) context.getBean("user");}
}
一、创建BeanFactory
首先,我们知道在使用Spring时,Spring会帮我们创建对象,省略自己new对象的过程。spring创建完对象后放到容器中。
而在Spring框架中,BeanFactory 是其中一个核心接口,可以理解为是Spring IOC容器的一种实现。
BeanFactory 负责创建和管理Bean、依赖注入、延迟初始化等功能。
BeanFactory相关的源码注释:
org.springframework.beans.factory.BeanFactory
java">/*** The root interface for accessing a Spring bean container.(用于访问 Spring bean 容器的根接口。)* ...* Bean factory implementations should support the standard bean lifecycle interfaces as far as possible.* The full set of initialization methods and their standard order is:* 1.BeanNameAware's setBeanName* 2.BeanClassLoaderAware's setBeanClassLoader* 3.BeanFactoryAware's setBeanFactory* 4.EnvironmentAware's setEnvironment* 5.EmbeddedValueResolverAware's setEmbeddedValueResolver* 6.ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)* 7.ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)* 8.MessageSourceAware's setMessageSource (only applicable when running in an application context)* 9.ApplicationContextAware's setApplicationContext (only applicable when running in an application context)* 10.ServletContextAware's setServletContext (only applicable when running in a web application context)* 11.postProcessBeforeInitialization methods of BeanPostProcessors* 12.InitializingBean's afterPropertiesSet* 13.a custom init-method definition* 14.postProcessAfterInitialization methods of BeanPostProcessors* On shutdown of a bean factory, the following lifecycle methods apply:* 1.postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors* 2.DisposableBean's destroy* 3.a custom destroy-method definition* 中文翻译:* Bean 工厂实现应尽可能支持标准的 Bean 生命周期接口。完整的初始化方法集及其标准顺序为:* 1.BeanNameAware 的 setBeanName* 2.BeanClassLoaderAware 的 setBeanClassLoader* 3.BeanFactory 的 setBeanFactory* 4.EnvironmentAware 的 setEnvironment* 5.EmbeddedValueResolverAware 的 setEmbeddedValueResolver* 6.ResourceLoaderAware setResourceLoader 的(仅在应用程序上下文中运行时适用)* 7.ApplicationEventPublisherAware setApplicationEventPublisher 的(仅在应用程序上下文中运行时适用)* 8.MessageSourceAware setMessageSource 的(仅在应用程序上下文中运行时适用)* 9.ApplicationContextAware setApplicationContext 的(仅在应用程序上下文中运行时适用)* 10.ServletContextAware setServletContext 的(仅在 Web 应用程序上下文中运行时适用)* 11.postProcessBeforeInitialization BeanPostProcessors 的方法* 12.初始化 Bean 的 afterPropertiesSet* 13.自定义 init-method 定义* 14.postProcessAfterInitialization BeanPostProcessors 的方法* 在 Bean 工厂关闭时,以下生命周期方法适用:* 1.postProcessBeforeDestruction DestructionAwareBeanPostProcessors 的方法* 2.DisposableBean 的 destroy* 3.自定义 destroy 方法定义*/
public interface BeanFactory {...
}
在BeanFactory接口的注释中写到BeanFactory是用于访问 Spring bean 容器的根接口和Spring执行流程。
ApplicationContext
ApplicationContext是BeanFactory的子接口,并提供了更多的企业级功能和更好的开发体验。如:支持更多的配置方式,如基于注解的配置、Java配置类,支持自动装配等。
org.springframework.context.ApplicationContext
java">public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {...
}
类图
BeanFactory和ApplicationContext的区别
- 初始化时机:
- ApplicationContext 默认采用立即初始化策略,会在应用启动时立即创建所有的单例Bean。也可以使用@Lazy注解来实现Bean的延迟初始化
- BeanFactory 采用懒加载策略,只有在第一次请求时才会创建Bean。
- 在Spring框架中,默认情况下使用的是ApplicationContext
- 自动装配:
- ApplicationContext 支持自动装配,可以自动检测并注入依赖。
- BeanFactory 不支持自动装配,需要显式地配置依赖关系。
- 额外的功能:
- ApplicationContext 提供了更多企业级功能,如国际化、事件传播、资源访问等。
- ApplicationContext 支持更多的配置方式,如基于注解的配置、Java配置类等。
更多信息可以看这篇文章:一文看懂 BeanFactory 和 ApplicationContext
补充
如何从容器中获取对象?
可以通过Aware接口来拿到ApplicationContext,通过applicationContext.getBean(User.class)拿到对应的User对象。
Aware接口这里先不展开说,可以理解成Aware是一个启标记作用的接口,只要有实体类实现了Aware接口的子接口。如ApplicationContextAware并且覆盖setApplicationContext(),spring会自动给this.applicationContext赋值。
java">public class Test implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public ApplicationContext getApplicationContext() {return applicationContext;}
}
二、读取xml等,将bean定义信息放入BeanDefinition
在BeanFactory创建好之后,接下来就该读取在xml、注解等配置文件中存放的bean定义信息了。
而在spring中通过BeanDefinitionReader接口进行读取bean定义信息。
BeanDefinitionReader相关的源码注释
org.springframework.beans.factory.support.BeanDefinitionReader
java">/*
Simple interface for bean definition readers. Specifies load methods with Resource and String location parameters.
Concrete bean definition readers can of course add additional load and register methods for bean definitions, specific to their bean definition format.
Note that a bean definition reader does not have to implement this interface.
It only serves as suggestion for bean definition readers that want to follow standard naming conventions.
bean定义阅读器的简单界面。使用资源和字符串位置参数指定加载方法。
具体的bean定义阅读器当然可以为bean定义添加额外的加载和注册方法,具体取决于它们的bean定义格式。
请注意,bean定义读取器不必实现此接口。
它仅作为希望读者遵循标准命名约定的bean定义的建议。
*/
public interface BeanDefinitionReader {...
}
将xml和注解中的bean定义信息读取出来后要装载到容器中(使用Map结构存放),使用BeanDefinitionMap的BeanDefinition存放Bean的定义信息。
BeanDefinition相关的源码注释
org.springframework.beans.factory.config.BeanDefinition
java">/*
A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations.
This is just a minimal interface:
The main intention is to allow a BeanFactoryPostProcessor such as PropertyPlaceholderConfigurer to introspect and modify property values and other bean metadata.
BeanDefinition描述了一个bean实例,该实例具有属性值、构造函数参数值以及具体实现提供的进一步信息。
这只是一个最小的接口:
主要目的是允许BeanFactory后处理器(如PropertyPlaceholderConfigurer)自检和修改属性值和其他bean元数据。
*/
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {...
}
三、对BeanDefinition中的属性值进行替换
在获取到BeanDefinition对象后,下一步进行创建bean对象时,要先进行属性值value的替换(替换成真正的值)
如以下数据源例子,当完成以下xml解析后会将id、class的属性值放到BeanDefinition对象中,但是此时可以看到在property标签中value的值是${jdbc.username}
,接下来需要完成属性值${jdbc.username}的替换。
<bean id="dataSource" class = "com.alibaba.druid.pool.DruidDataSource"><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="url" value="${jdbc.url}"></property><property name="driverClassName" value="${jdbc.driverClassName}"></property>
</bean>
在Spring中使用BeanFactoryPostProcessor接口的子抽象类PlaceholderConfigurerSupport,对BeanDefinition中为占位符的属性值,替换为具体的值。
PlaceholderConfigurerSupport相关的源码注释
org.springframework.beans.factory.config.PlaceholderConfigurerSupport
java">/**
Abstract base class for property resource configurers that resolve placeholders in bean definition property values.
Implementations pull values from a properties file or other property source into bean definitions.
The default placeholder syntax follows the Ant / Log4J / JSP EL style:
${...}
Example XML bean definition:<bean id="dataSource" class="org. springframework. jdbc. datasource. DriverManagerDataSource"/><property name="driverClassName" value="${driver}"/><property name="url" value="jdbc:${dbname}"/></ bean>属性资源配置器的抽象基类,用于解析 bean 定义属性值中的占位符。实现将值从属性文件或其他属性源拉取到 Bean 定义中。
默认占位符语法遵循 Ant / Log4J / JSP EL 样式:
${...}
XML Bean 定义示例:<bean id="dataSource" class="org. springframework. jdbc. datasource. DriverManagerDataSource"/><property name="driverClassName" value="${driver}"/><property name="url" value="jdbc:${dbname}"/></ bean>
*/
public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurerimplements BeanNameAware, BeanFactoryAware {/** Default placeholder prefix: {@value}. */public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";/** Default placeholder suffix: {@value}. */public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";/** Default value separator: {@value}. */public static final String DEFAULT_VALUE_SEPARATOR = ":";...
}
补充
BeanFactoryPostProcessor.postProcessBeanFactory()
在所有Bean定义被读取之后,并在所有Bean实例化之前,可以调用BeanFactoryPostProcessor.postProcessBeanFactory()来修改Bean定义信息。
org.springframework.beans.factory.config.BeanFactoryPostProcessor
java">/*** Factory hook that allows for custom modification of an application context's* bean definitions, adapting the bean property values of the context's underlying* bean factory.* Factory 钩子,允许自定义修改应用程序上下文的 bean 定义,调整上下文的基础 bean 工厂的 bean 属性值*/
@FunctionalInterface
public interface BeanFactoryPostProcessor {/*** Modify the application context's internal bean factory after its standard* initialization. All bean definitions will have been loaded, but no beans* will have been instantiated yet. This allows for overriding or adding* properties even to eager-initializing beans.** 在标准初始化后修改应用程序上下文的内部 Bean 工厂。* 所有 bean 定义都已加载,但尚未实例化任何 bean。这允许覆盖或添加属性,甚至允许预先初始化 bean。*/void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}
可以自定义的 BeanFactoryPostProcessor 实现类,对Bean进行处理。
java">import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;/*** @author qf* @since 2024/10/16 19:58*/
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 获取名为user的Bean定义if (beanFactory.containsBeanDefinition("user")) {// 修改user的属性值beanFactory.getBeanDefinition("user").getPropertyValues().add("id", 10001L);}// 拿到所有 bean 的名称String[] beanNames = beanFactory.getBeanDefinitionNames();for (String beanName : beanNames) {// 对每个Bean进行处理System.out.println("对BeanDefinition: " + beanName +",进行处理");}}
}
BeanFactoryPostProcessor接口与BeanPostProcessor接口
-
BeanFactoryPostProcessor 接口允许我们在Spring容器加载Bean定义之后、实际创建Bean实例之前修改这些Bean定义。
它通常用于动态修改配置元数据(如XML配置文件或注解配置)。BeanFactoryPostProcessor操作的是BeanFactory(接口),主要是对Bean 定义进行操作 -
BeanPostProcessor 接口允许我们在Spring容器实例化Bean之后但在初始化前对Bean进行处理。
它可以在Bean对象实例化后对其进行增强或修改,例如设置额外的属性、包装Bean等。BeanPostProcessor操作的是Bean(对象),是在Bean实例的生命周期阶段进行操作。
更多信息可以看这篇文章:一文看懂 BeanFactoryPostProcessor 与 BeanPostProcessor 接口
四、Bean实例化
接下来进行实例化时需要注意,Spring不仅需要在堆中开辟一块空间,还需要给对象中的属性设置属性值,因此分为实例化和初始化。
创建 Bean 实例(实例化):根据 Bean Definition 中的类信息,使用反射机制创建 Bean 的实例。
例如,如果 Bean Definition 指定的类是com.qf.User,Spring会使用Class.forName(“com.qf.User”)获取类对象,然后调用其默认构造函数(如果存在)来创建实例。如果类没有默认构造函数,且在配置中没有指定其他构造函数参数,将会抛出异常。
补充
Spring Bean生命周期图
文中spring容器接下来的操作对照以上图片
AbstractAutowireCapableBeanFactory.createBeanInstance()
当 Spring 容器在实例化时调用该方法,createBeanInstance()就是负责根据 Bean 的定义信息(如类名、构造函数参数等)来实际生成一个 Bean 对象。
进入Spring源码
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
java">protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {//拿到class对象Class<?> beanClass = resolveBeanClass(mbd, beanName);...// No special handling: simply use no-arg constructor.//如果没有特殊处理,则使用无参构造器创建实例。return instantiateBean(beanName, mbd);
}
向下执行
↓
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean
↓
org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)
java">@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {if (!bd.hasMethodOverrides()) {...try {if (System.getSecurityManager() != null) {...}else {//获取构造器constructorToUse = clazz.getDeclaredConstructor();}...}...//进入return BeanUtils.instantiateClass(constructorToUse);}...
}
org.springframework.beans.BeanUtils#instantiateClass(java.lang.reflect.Constructor, java.lang.Object…)
java">public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {...if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {return KotlinDelegate.instantiateClass(ctor, args);}else {...//对象创建return ctor.newInstance(argsWithDefaultValues);}}...
}
五、依赖注入
属性赋值(依赖注入)发生在 Bean 实例化之后,但在调用初始化方法之前。
这个过程也被称为依赖注入(Dependency Injection,DI)。其目的是将 Bean 所依赖的其他资源(如其他 Bean、配置文件中的值等)注入到该 Bean 中。
Spring 容器会根据配置文件或注解中的信息,调用 Bean 的 set 方法为其属性赋值。
注入方式:
1.简单属性注入:
在传统的 XML 配置中,可以通过标签来为 Bean 的属性赋值。如:
java"> <bean id="user" class="com.qf.entity.User"><property name="name" value="zhangsan"></property><property name="age" value="1"></property></bean><bean id="userService" class="com.qf.service.UserService"><property name="userRepository" ref="userRepository"/></bean><bean id="userRepository" class="com.qf.repository.UserRepository"/>
在上述示例中,userService Bean 的userRepository属性通过ref属性引用了另一个名为userRepository的 Bean。Spring 会在容器中查找userRepository Bean,并将其注入到UserService的userRepository属性中。
2.基于注解的属性赋值
@Autowired注解
@Autowired注解是 Spring 中最常用的用于依赖注入的注解之一。当一个 Bean 的属性使用@Autowired注解时,Spring 会自动在容器中查找合适的 Bean 来注入。如:
java">@Component("userService")
public class UserService {@Autowiredprivate UserRepository userRepository;...
}
在上述示例中,UserService的userRepository属性使用了@Autowired注解。Spring 会在容器中查找类型为UserRepository的 Bean,并将其注入到userRepository属性中。如果容器中有多个UserRepository类型的 Bean,Spring 还可以根据@Qualifier注解来指定具体要注入的 Bean。
@Value注解
@Value注解用于注入简单的值,如字符串、数字等。
java">@Component("userService")
public class UserService {@Value("${user.service.name}")private String serviceName;...
}
在上述示例中,@Value注解从配置文件(如application.properties或application.yml)中读取user.service.name对应的键值,并将其注入到serviceName属性中。
六、Bean初始化
Aware
在完成了属性赋值之后,接下来进行检查该 Bean 是否实现了各种Aware相关接口,有则使用set()设置属性值。
Aware接口是一个空接口,可以理解为是一个标记接口,方便在一个统一的方法(AbstractAutowireCapableBeanFactory.invokeAwareMethods)中进行判断处理赋值,在子接口写出各自的set方法。
**Aware接口方法的主要作用是让 Bean 能够获取 Spring 容器的相关资源和信息,以便在后续的初始化和业务逻辑中使用。**可以理解为之前的属性赋值是将我们自定义属性的值进行赋值,而使用Aware可以让我们拿到Spring容器内部的容器对象。
如:Bean 实现了 ApplicationContextAware 接口,此时Spring会通过 setApplicationContext() 给Bean中的ApplicationContext属性值赋值。
org.springframework.context.ApplicationContextAware
java">public interface ApplicationContextAware extends Aware {void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
在实际项目中的使用:
java">public class SpringContextUtil implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public ApplicationContext getApplicationContext() {return applicationContext;}
}
以上类中如setApplicationContext()方法是spring容器进行调用的,在invokeAwareMethods中统一调用。
当实现ApplicationContextAware接口后,当前类中的setApplicationContext为接口中setApplicationContext方法的实现方法,会在执行AbstractAutowireCapableBeanFactory.invokeAwareMethods()时由容器进行赋值。Spring源码的具体实现如下:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
java">private void invokeAwareMethods(String beanName, Object bean) {//如果 bean 是 Aware 实例if (bean instanceof Aware) {//如果bean是BeanNameAware实例if (bean instanceof BeanNameAware) {//调用 bean 的setBeanName方法((BeanNameAware) bean).setBeanName(beanName);}//如果bean是 BeanClassLoaderAware 实例if (bean instanceof BeanClassLoaderAware) {//获取此工厂的类加载器以加载Bean类(即使无法使用系统classLoader,也只能为null)ClassLoader bcl = getBeanClassLoader();if (bcl != null) {//调用 bean 的 setBeanClassLoader 方法((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}//检查bean是否实现了BeanFactoryAware,如果是,则调用其setBeanFactory方法设置工厂实例。if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}
}
BeanPostProcessor 的前置处理
接下来进行BeanPostProcessor 的前置处理
如果有 BeanPostProcessor 类型的后处理器,它们的 postProcessBeforeInitialization 方法会被调用,允许在正式初始化之前对 Bean 进行额外的操作。
调用自定义初始化方法
- 调用 init-method:如果 Bean 定义中指定了 init-method 属性,Spring 会在完成依赖注入后会调用指定的方法来进行初始化操作。这通常用于执行一些资源分配、初始化连接池或其他启动时的任务等。
- 实现 InitializingBean 接口:如果 Bean 实现了 InitializingBean 接口,则会调用其 afterPropertiesSet 方法。该接口提供了一个标准的方式来完成初始化工作,让 Bean 有机会执行额外的初始化操作,如验证属性值、建立额外的连接等。
补充
当执行完属性赋值步骤之后,对象的创建和属性的赋值都完成了,那么此时对象是否可以直接拿来使用了?
理论上说此时是可以拿来使用了,但是Spring要考虑扩展性,因此接下来调用BeanPostProcessor 的 postProcessAfterInitialization 方法(AOP在此实现)
七、Bean 的后置处理
一旦初始化方法执行完毕,接下来会调用所有已注册bean的BeanPostProcessor的postProcessAfterInitialization方法,这是最后一次进行修改或包装 Bean,此时 bean 已经基本准备就绪,可以进行一些后置处理操作,如 AOP 代理创建、添加额外的行为或对 bean 进行修改等。
例如,对于一个普通的业务服务类 bean,在其构造函数执行、依赖注入完成并且初始化方法执行后,Spring 会遍历所有的BeanPostProcessor并调用它们的postProcessAfterInitialization方法来对这个 bean 进行进一步处理。
postProcessAfterInitialization方法返回的对象将替换容器中原本的 bean 实例。对于需要进行 AOP 增强的 bean,返回的是代理对象,而这个代理对象包含了切面逻辑(如通知方法,包括前置通知、后置通知、环绕通知等)。当调用被代理 bean 的方法时,实际上是调用代理对象的相应方法,代理对象会根据切面配置在合适的时机执行增强逻辑,然后再调用原始 bean 的目标方法,实现增强逻辑与业务逻辑。
例如,在一个方法执行前,代理对象可以执行前置通知逻辑(如权限检查),方法执行后执行后置通知逻辑(如记录日志),从而实现了 AOP 对业务方法的非侵入式增强。
BeanPostProcessor中有一个很重要的实现类叫AbstractAutoProxyCreator
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
java">public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = this.getCacheKey(bean.getClass(), beanName);// 判断当前bean是否正在被代理,如果正在被代理则不进行封装if (this.earlyProxyReferences.remove(cacheKey) != bean) {// 如果它需要被代理,则需要封装指定的bean//这里进入wrapIfNecessaryreturn this.wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
}
↓
进入wrapIfNecessary
java">protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {...if (specificInterceptors != DO_NOT_PROXY) {...//根据获取到的Advices和Advisors为当前bean生成代理对象//进入方法Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));...} ...
}
↓
proxyFactory.getProxy()
↓
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
java">public Object getProxy(@Nullable ClassLoader classLoader) {//createAopProxy()用来创建我们的代理工厂return this.createAopProxy().getProxy(classLoader);
}
↓
org.springframework.aop.framework.AopProxy
java">public interface AopProxy {Object getProxy();Object getProxy(@Nullable ClassLoader var1);
}
点击AopProxy接口实现类可以看到JDK动态代理和CGLib动态代理
八、使用Bean
执行完BeanPostProcessor的postProcessAfterInitialization()方法后,生成完整对象在spring容器中。可通过context.getBean()获得该完整对象。
九、销毁Bean
当 Bean 不再需要时(例如,在单例作用域下,当应用上下文关闭时),Spring 会调用相应的销毁方法(如 destroy-method 或 DisposableBean 接口中的 destroy 方法)来清理资源。
总结
以下是Spring容器启动时的主要生命周期事件顺序:
- 创建BeanFactory,用于创建和管理Bean、依赖注入、延迟初始化等功能
- 通过BeanDefinitionReader读取配置文件或注解加载到BeanDefinition。
- 调用 BeanFactoryPostProcessor.postProcessBeanFactory(),用于修改Bean定义。(BeanDefinition中的属性值进行替换)
- 创建Bean实例(实例化)。根据BeanDefinition创建Bean实例。
- 设置Bean属性(属性赋值)。Spring 容器调用 set 方法为 Bean 的属性赋值(依赖注入)。
- 对 Bean 实现了Aware接口,进行set()设置属性值。
- 调用 BeanPostProcessor.postProcessBeforeInitialization()。对Bean进行预处理
- 调用Bean的初始化方法(如@PostConstruct或InitializingBean.afterPropertiesSet)。
- 调用 BeanPostProcessor.postProcessAfterInitialization()。对Bean进行后处理
- 使用Bean。将Bean添加到Spring容器中,Bean 准备就绪,可以被其他 Bean 使用。
- 销毁Bean(如果容器关闭)。