前言:
Spring主要功能创建对象(俗称IOC),
Bean的生命周期流程图

1、生成BeanDefinition
spring启动会进行扫描执行如下方法
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents
Spring的扫描流程图

- 根据ResourcePatternResolver 获取指定路径下所有的.class文件【最终生成 Resource 对象】
- 遍历 Resource 集合
- 利用MetadataReaderFactory 解析 Resource 获取metadateReader
- 对metadataReader 进行 excludeFilters和 includeFilters ,
- 若excludeFilters 匹配直接返回false,
- 若 includeFiletes 匹配还要判断,是否有@Conditional ,如果有则需要判断@Conditional 注解筛选是否筛选过,不能筛选 直接false
- 筛选通过后,还要判断
- 是否独立、【不是接口或抽象】、如果是抽象,类上面是否添加@Lookup注解 【三个条件缺一不可】
- 最终将 ScannedGenericBeanDefinition 生成BeanDefinition 对象返回
其中 @Conditional 的注解的作用
@Conditional 是 Spring 4.0 引入的核心注解,用于条件化地创建 Bean。它允许根据特定条件决定是否注册 Bean 到 Spring 容器中。
除了自定义条件,Spring 还提供了一些内置的条件注解,这些注解都是 @Conditional 的扩展,使用起来更加方便:
- @ConditionalOnBean:当容器中存在指定 Bean 时。
- @ConditionalOnMissingBean:当容器中不存在指定 Bean 时。
- @ConditionalOnClass:当类路径中存在指定类时。
- @ConditionalOnMissingClass:当类路径中不存在指定类时。
- @ConditionalOnProperty:当指定的属性有指定的值时。
- @ConditionalOnResource:当类路径中存在指定资源时。
- @ConditionalOnWebApplication:当是 Web 应用时。
- @ConditionalOnNotWebApplication:当不是 Web 应用时。
- @ConditionalOnExpression:当 SpEL 表达式为 true 时。
@Conditional 注解 demo案例:
StuService Bean的创建 要依赖于 StuServiceCondition
c
@Component
@Conditional(StuServiceCondition.class)
public class StuService {
public void test(){
System.out.println("stu test ...");
}
}
c
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class StuServiceCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 检查某个属性是否存在
return context.getEnvironment()
.containsProperty("stu.service.enabled");
}
}
这时获取bean 为stuService 找不到异常。
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'stuService' available...
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
创建MetadataReader 注意点:
org.springframework.core.type.classreading.CachingMetadataReaderFactory#getMetadataReader
CachingMetadataReaderFactory解析某个.class文件得到 MetadataReader对象,利用的是ASM技术,并没有加载这个类到JVM。最终得到的ScannedGenericBeanDefinition对象,beanClass属性存储当前的类的名称,而不是class对象。
2、合并BeanDefinition
在通过BeanDefinition之后,就可以根据BeanDefinition创建Bean对象。在spring中支持父子BeanDefinition,和Java中继承相似
比如:
spring.xml
c
<bean id="parent" class="com.dx.service.Parent" scope="prototype"/>
<bean id="child" class="com.dx.service.Child" />
测试:
c
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
System.out.println(applicationContext.getBean("child"));
System.out.println(applicationContext.getBean("child"));
System.out.println(applicationContext.getBean("child"));
测试结果:
com.dx.service.Child@ef9296d
com.dx.service.Child@ef9296d
com.dx.service.Child@ef9296d
如果将xml修改为:
c
<bean id="parent" class="com.dx.service.Parent" scope="prototype"/>
<bean id="child" class="com.dx.service.Child" parent="parent" />
测试的结果是
com.dx.service.Child@ef9296d
com.dx.service.Child@36c88a32
com.dx.service.Child@7880cdf3
child可以继承parent的 scope,
- 子如果有scope 则使用自己的
- 子没有scope,继承父类scope,父类若没有scope有parent的属性,同样的继承逻辑
源码的大概如下: - 根据beanName判断是否合并过,合并过直接退出
- 判断当前的bean是否有父类,
- 如果没有设置 当前bean为RootBeanDefinition
- 如果有循环获取 bean的父bean
- 覆盖父定义属性(子覆盖父)
c
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
// 1. 检查是否已经合并过
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd == null) {
// 2. 如果没有父定义,直接转换为RootBeanDefinition
if (bd.getParentName() == null) {
mbd = new RootBeanDefinition(bd);
} else {
// 3. 递归合并父定义
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
pbd = getMergedBeanDefinition(parentBeanName);
}
// ...
// 4. 深度拷贝父定义
mbd = new RootBeanDefinition(pbd);
// 5. 覆盖父定义属性(子覆盖父)
mbd.overrideFrom(bd);
}
// 6. 缓存合并结果
this.mergedBeanDefinitions.put(beanName, mbd);
}
return mbd;
}
}
3、加载类
BeanDefinition合并之后,就可以创建Bean的对象执行的方法是
org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass
创建bean就必须实例化对象,实例化要先加载类所对应class
c
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
方法的主要实现是:
c
// 如果是beanClass就直接返回
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
// 如果beanClass没有被加载,会根据doResolveBeanClass
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);
}
如果beanClass 属性的类型是Class 直接返回,不是则根据类名加载(doResolveBeanClass(mbd, typesToMatch))
会利用BeanFactory所设置的类加载器加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()类加载
ClassUtils.getDefaultClassLoader()类加载方法:
- 优先获取当前线程的类加载器
- 当前线程类加载为空,返回ClassUtils.class.getClassLoader()
- 如果ClassUtils.class.getClassLoader() 也为空,则ClassLoader.getSystemClassLoader()
4、实例化前
BeanDefinition 对应的类加载成功后,实例化对象前 Spring提供一个扩展点允许某个对象、某些对象实例化前做些额外的工作
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
c
import com.zhouyu.service.StuService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class DxBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("stuService".equals(beanName)){
System.out.println("加载 stuService 初始化之前");
// Spring将直接使用这个对象
return new StuService();
}
// 返回null则走正常流程
return null;
}
}
InstantiationAwareBeanPostProcessor 的
postProcessBeforeInstantiation 除了常见的创建代理对象外,还有以下重要作用:
1,完全绕过spring的生命周期
c
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 如果返回非null对象,Spring将:
// 1. 跳过默认构造函数调用
// 2. 跳过后置处理器链的后续处理
// 3. 跳过属性注入
if (beanName.equals("specialBean")) {
return new SpecialBean(); // Spring将直接使用这个对象
}
return null; // 返回null则走正常流程
}
2、根据条件Bean创建
c
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 根据条件决定是否创建Bean
if (shouldSkipCreation(beanClass, beanName)) {
return new NoOpBean(); // 返回一个占位对象
}
// 根据环境变量/配置决定实现类
if (beanClass.isAssignableFrom(Service.class)) {
return isProduction() ?
new ProductionService() :
new MockService();
}
return null;
}
3、对象池/缓存管理
c
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
if (beanClass.isAnnotationPresent(Poolable.class)) {
// 从对象池获取实例,而不是新建
Object pooledInstance = objectPool.acquire(beanClass);
if (pooledInstance != null) {
return pooledInstance; // 返回池中对象
}
}
return null;
}
4、性能优化场景
c
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 对于频繁创建的原型Bean,使用对象复用策略
if (isHighFrequencyPrototype(beanClass)) {
return prototypeReuseStrategy.createOrReuse(beanClass);
}
// 对于已知的无状态Bean,直接返回共享实例
if (isStateless(beanClass)) {
return getSharedInstance(beanClass);
}
return null;
}
postProcessBeforeInstantiation 使用注意点
1、跳过正常的生命周期 :返回null 会跳过
- postProcessAfterInstantiation
- 属性注入 (populateBean)
- 初始化回调 (afterPropertiesSet, init-method)
- postProcessBeforeInitialization
- postProcessAfterInitialization
2、需要手动处理依赖
c
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
MyBean bean = new MyBean();
// 需要手动注入依赖
bean.setDependency(manualLookup());
// 手动调用初始化
bean.init();
return bean;
}
3、与 AOP 的协调:如果在此创建代理,需要确保与其他 AOP 配置协调一致
5、实例化
会根据 BeanDefinition 创建一个对象。
5.1 Supplier创建对象
判断Beandefinition 中是否设置Supplier,如果设置了 则调用Supplier的get() 设置 Supplier
c
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(Person.class);
// 设置 supplier
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
@Override
public Object get() {
// 这里可以编写创建逻辑
Person person = new Person();
person.setAge(18);
person.setName("张三");
return person;
}
});
// 注册bean
applicationContext.registerBeanDefinition("person",beanDefinition);
System.out.println(applicationContext.getBean("person"));
====== 执行结果=====
Person{age=18, name='张三'}
Supplier 基础概念和作用
1,Supplier 是什么
是 Java 8 引入的函数式接口,表示一个结果的提供者:
c
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
1.2 在Spring中作用:
1.延迟实例化:将 Bean 的创建逻辑封装起来,按需调用
2.灵活性:允许运行时动态决定如何创建 Bean
3.与 BeanDefinition 解耦:将创建逻辑从 BeanDefinition 中分离
2、工厂方法创建对象
如果没有设置Supplier,检查是否BeanDefinition中是否设置 factory-method
sprin.xml
c
<bean id="stuService" class="com.zhouyu.service.StuService" factory-method="createStuServiceFactory"/>
c
public class StuService {
public static StuService createStuServiceFactory(){
System.out.println("this StuService createFactory");
return new StuService();
}
public void test(){
System.out.println("stu test ...");
}
}
c
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
new XmlBeanDefinitionReader(applicationContext).loadBeanDefinitions("spring.xml");
System.out.println(applicationContext.getBean("stuService"));
3、推断方法 @Lookup注解
c
import org.springframework.stereotype.Component;
@Component
public class StuService {
public void test(){
System.out.println("stu test ...");
}
}
c
创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
StuService stuService = (StuService) applicationContext.getBean("stuService");
stuService.test();
执行结果
stu test ...
测试@Conditional注解
c
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Component
@Conditional(StuServiceCondition.class)
public class StuService {
public void test(){
System.out.println("stu test ...");
}
}
c
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class StuServiceCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 检查某个属性是否存在
return context.getEnvironment()
.containsProperty("stu.service.enabled");
}
}
执行结果报:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'stuService' available...
6、BeanDefinition的后置处理器
比如Spring中使用
c
@Component
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
System.out.println(" AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition method ");
}
}
7、实例化后
postProcessAfterInstantiation 作用
- 在Bean的实例化后、属性注入前执行
- 可以返回false阻止Spring对该Bean进行属性注入
- 适合用于自定义初始化逻辑或条件判断
典型应用场景: - 动态控制属性注入
- 实现延迟注入
- 属性值验证和转换
- 特殊Bean的预处理
属性填充案例:
c
@Component
public class DxInstanceAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("stuService".equals(beanName)) {
PerSon perSon = new PerSon();
perSon.setAge(12);
perSon.setName("张三");
System.out.println(perSon);
}
return true;
}
}
8、自动注入
9、处理属性
InstantiationAwareBeanPostProcessor.postProcessProperties() 是Spring框架中一个非常重要的扩展点,它在Bean的生命周期中扮演着关键角色。
主要作用包括:
1.处理注解驱动的依赖注入:例如,@Autowired、@Value、@Inject、@Resource等注解的解析和注入。
2.属性值的后处理:可以对属性值进行转换、验证、加密/解密等操作。
3.动态添加属性:根据某些条件动态添加属性。
4.跳过某些属性的注入:通过返回null或修改PropertyValues来控制哪些属性需要注入。
比如Spring内置实现
AutowiredAnnotationBeanPostProcessor
c
// 主要职责:处理 @Autowired、@Value、@Inject 注解
public class AutowiredAnnotationBeanPostProcessor {
@Override
public PropertyValues postProcessProperties(
PropertyValues pvs, Object bean, String beanName) {
// 1. 获取或构建注入元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 2. 执行实际的注入操作
metadata.inject(bean, beanName, pvs);
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection failed", ex);
}
// 3. 返回可能被修改的 PropertyValues
return pvs;
}
private void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) {
// 字段注入
for (AutowiredFieldElement field : this.autowiredFields) {
field.inject(bean, beanName, pvs);
}
// 方法注入
for (AutowiredMethodElement method : this.autowiredMethods) {
method.inject(bean, beanName, pvs);
}
}
}
注解解析
处理各种依赖注入注解属性处理
修改、添加、删除属性值值转换
类型转换、占位符解析、SpEL计算
条件控制:根据条件决定是否注入某些属性
验证检查:属性值验证和约束检查
10、执行Aware
1.获取Bean在容器中的名称:通过实现BeanNameAware接口,Bean可以知道自己在容器中配置的名称。
2.获取BeanFactory:通过实现BeanFactoryAware接口,Bean可以获取到BeanFactory,从而可以手动获取其他Bean,或者进行一些高级操作。
3.获取ApplicationContext:通过实现ApplicationContextAware接口,Bean可以获取到ApplicationContext,从而可以访问容器上下文,例如获取其他Bean、发布事件、访问环境变量等。
4.获取环境配置:通过实现EnvironmentAware接口,Bean可以获取到Environment对象,从而可以访问配置属性、profiles等。
5.资源加载:通过实现ResourceLoaderAware接口,Bean可以获取到ResourceLoader,从而可以加载类路径或文件系统中的资源。
6.国际化:通过实现MessageSourceAware接口,Bean可以获取到MessageSource,从而可以进行国际化消息的解析。
7.应用事件发布:通过实现ApplicationEventPublisherAware接口,Bean可以获取到ApplicationEventPublisher,从而可以发布应用事件。
8.嵌入式值解析:通过实现EmbeddedValueResolverAware接口,Bean可以获取到StringValueResolver,从而可以解析嵌入式值(例如SpEL表达式)。
使用 Aware 的场景清单

c
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;
@Component
public class BeanIdentityService implements BeanNameAware, BeanClassLoaderAware {
private String beanName;
private ClassLoader classLoader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
System.out.println("current classLoader :" + classLoader);
}
@Override
public void setBeanName(String name) {
// 场景:日志记录、监控、动态配置
this.beanName = beanName;
System.out.println("current bean name :" + beanName);
}
}
11、初始化前
BeanPostProcessor.postProcessBeforeInitialization()
c
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class DxPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("stuService".equals(beanName)){
System.out.println("初始化之前");
}
return bean;
}
}
12、初始化
c
// 1. @PostConstruct 注解方法
@PostConstruct
public void initMethod1() {
// JSR-250 标准,最先执行
}
// 2. InitializingBean 接口的 afterPropertiesSet 方法
@Override
public void afterPropertiesSet() throws Exception {
// Spring 接口方式,第二执行
}
// 3. XML/@Bean 配置的 init-method
// XML: <bean id="demo" class="com.xx.xx.Demo" init-method="customInit"/>
// @Bean: @Bean(initMethod = "customInit")
public void customInit() {
// 自定义方法,最后执行
}
13、初始化后
这个是bean创建的生命周期最后一步。
c
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class DxPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("stuService".equals(beanName)){
System.out.println("初始化之后");
}
return bean;
}
}
喜欢我的文章记得点个在看,或者点赞,持续更新中ing...