springboot之IoC学习
IoC:Inversion of Control,控制反转。
IoC容器是spring中非常重要的一个概念,它是一种思想。
IoC的作用就是将整个业务代码解耦,使得各个模块之间不再直接关联。下面的图可以清晰地描述这种关系:
我们看上面的例子来解释控制反转的事情。
假如对象A要依赖于对象B。
在传统编程中,我们会在A中主动取创建B,这是一种主动控制行为,代码类似下面
public class TestP {
private Yaoming b;
public TestP(Yaoming b){
this.b = b;
}
}
而有了IoC容器之后,当A需要B时,Ioc容器负责去创建对象B,而A不再需要主动去创建对象。就是将主动行为变成了一种被动的行为,这就是控制反转的含义。
刚才提到了IoC是一种思想,它的其中一种实现就是依赖注入(DI),在下面有个参考资料通俗解释了DI,我觉得很形象,它是用USB和电脑的例子解释的,有兴趣的可以参考下面的文章,我也不再赘述。
在Spring中,有了IoC,我们可以按照下面方式开发:
public class ActivityManageTest {
private static final Logger logger = LoggerFactory.getLogger("logStash");
private static final Logger locallogger = LoggerFactory.getLogger(ActivityManageTest.class);
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
private HashSet<String> hashSet = new HashSet<>();
@Autowired
ActivityManageService activityManageService;
上面的activityManageService就是我们依赖的对象,这里就不用调用方再去管理该对象,其创建和销毁等过程完全交给IoC容器来实现。看到这,应该很清楚地看到,IoC容器的加入,让我们的开发变得更加简单,且利用Ioc统一管理这些对象,更加规范。
Ioc容器目前在很多成熟的框架都有应用,比如laravel(php)的服务容器以及spring系列等等。他们实现的最基本的方法就是通过反射,即利用反射技术动态地创建对象。
本文主要学习springboot的容器(相对于spring,不再是依赖众多的xml文件)。
在Spring系列中,Ioc容器的两个重要模块是BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的扩展。
一、BeanFactory
先看几个重要的概念
1、BeanDefinition
它是对Bean对象的封装,在Bean初始化过程中,会将Bean的信息都存储到BeanDefinition。其就是sping对Bean的一种定以,后续对Bean的操作,实际上是对BeanDefinition的操作。看源码也可以看到Spring中保存注册bean的map的value就是BeanDefinition。
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
看一下它的源码:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String var1);
@Nullable
String getParentName();
void setBeanClassName(@Nullable String var1);
@Nullable
String getBeanClassName();
void setScope(@Nullable String var1);
@Nullable
String getScope();
void setLazyInit(boolean var1);
boolean isLazyInit();
void setDependsOn(@Nullable String... var1);
@Nullable
String[] getDependsOn();
void setAutowireCandidate(boolean var1);
boolean isAutowireCandidate();
void setPrimary(boolean var1);
boolean isPrimary();
void setFactoryBeanName(@Nullable String var1);
@Nullable
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String var1);
@Nullable
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !this.getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !this.getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String var1);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String var1);
@Nullable
String getDestroyMethodName();
void setRole(int var1);
int getRole();
void setDescription(@Nullable String var1);
@Nullable
String getDescription();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
上面包含bean类名,是否单例等等属性,其实它是一个接口,它还有几种实现类,如ChildBeanDefinition等。
2、BeanDefinitionRegistry
从其名字也可以看到,它的作用就是把BeanDefinition注册到IoC容器中。看一下它的源码:
public interface BeanDefinitionRegistry extends AliasRegistry {
//注册bean
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
//移除bean
void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String var1);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String var1);
}
同样,它也是一个接口。
3、BeanFactory
它是一个bean工厂类,提供了已注册Bean对象的获取等操作,看以下它的接口定以
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> var1);
<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
其中最重要的就是getBean方法,当我们在实际要获取某个对象时,底层都是通过该方法。
二、ApplicationContext
其实它是BeanFactory的扩展,目前也基本上都使用它。看一下继承关系图:
它除了继承BeanFactory,还继承了其他几个类:
- MessageSource:支持不同的信息源,支持国际化实现
- ResourcePatternResolver:访问资源,使得我们可以从不同的地方获取到Bean定义
- ApplicationEventPublisher:提供事件机制,跟Bean的整个生命周期结合,方便扩展
ApplicationContext有很多的实现类,其中一个是ConfigurableApplicationContext,它提供了几个关键方法:refresh()和 close(),让 ApplicationContext 具有启动、刷新和关闭应用上下文的能力。在应用上下文关闭的情况下调用 refresh()即可启动应用上下文,在已经启动的状态下,调用 refresh()则清除缓存并重新装载配置信息,而调用close()则可关闭应用上下文。
对于一个Bean来说,它主要经历了定以和初始化两个过程,大致如下图:
首先根据源码,分析一下启动阶段。
看一下一个调用的流程例子:
从应用启动入口开始:
SpringApplication.run(HbnnshopApplication.class, args);
看一下run方法:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
首先是创建应用上下文:
context = this.createApplicationContext();
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch(this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
}
return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
接下来创建IoC容器:
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); this.refreshContext(context);
其中,prepareContext源码:
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
this.applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
this.load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
其具体操作包括设置环境变量,加载两个单例bean等等,具体可以移步到下面的prepareContext的文章。
下面重点看一下refresh,它是IoC容器创建的关键部分。
看下其源码:
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);
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();
}
}
}
1、obtainFreshBeanFactory 主要解析配置文件,并装载Beandinition,添加到Map.除了resources下面定以的XML配置文件,还会解析@Controller、@Service、@Component、@Repository等注解,一并解析为BeanDifiniton,并添加到BeanFactory(实现类应用上下文的实现类)的Map中。主要加载的内容包括:
beanDefinitionNames缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 集合。
beanDefinitionMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和 BeanDefinition 映射。
aliasMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和别名映射。
更详细的资料可参考:
Spring IoC:obtainFreshBeanFactory 详解
2、prepareBeanFactory是准备工作,会注册ResouceLoader,ApplicationEventPublisher等依赖,添加BeanPostProcessor。
3、接着postProcessBeanFactory,它的作用主要是执行后续的一些BeanFactory操作,具体的还要看具体的实现类。
4、this.invokeBeanFactoryPostProcessors(beanFactory)
它会获取注册到上下文的BeanFactoryPostProcessor,它主要是在实例化Bean之前对Bean进行修改,相当于对Bean的一种扩展。看一下官网描述:
Allows for custom modification of an application context's bean definitions, adapting the bean property values of the context's underlying bean factory. Application contexts can auto-detect BeanFactoryPostProcessor beans in their bean definitions and apply them before any other beans get created. A BeanFactoryPostProcessor may interact with and modify bean definitions, but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects. If bean instance interaction is required, consider implementing BeanPostProcessor instead.
它主要使用了两种processor:regularPostProcessors和registryProcessors接口.
比较典型的就是ConfigurationClassPostProcessor,它实现了上面两个接口,其作用:
-
ConfigurationClassPostProcessor#postProcessBeanFactory
:主要负责在实例化Bean的过成中,对Bean进行增强,比如实现CGLIB代理,添加后值处理器,ImportAwareBeanPostProcessor等等。
例子:
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
}
我定以了一个配置类,加了@Configuration注解,我们测试一下是否走了代理。
@Autowired
RedisConfig redisConfig;
System.out.println(redisConfig.getClass().getName());
输出:
com.hnshop.hbnnshop.config.RedisConfig$$EnhancerBySpringCGLIB$$cf6a9ff4
可以看到,它使用了cglib代理.
其实除了@Configuraton,@Component等等凡是该类解析的都类似。
-
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
:负责扫描我们的程序,类如@Componet,@Import,
ComponentScan等注解,根据程序的中Bean创建BeanDefinition
,并注册到容器中。
具体关于这个类的介绍,可参考: ConfigurationClassPostProcessor —— Spring中最!最!最!重要的后置处理器!没有之一!!!
4、注册BeanFactoryPostProcessor
后续的流程就不说了,就是初始化小戏院,注册监听器等等。只要说一点,Sring的Bean是采用懒加载的模式,在启动时,不会真正初始化。
上面已经说了BeanFactory有个方法是getBean,他就是用来获取对象的。它的实现类有很多
- impleJndiBeanFactory - spring beanFactory接口的基于jndi的简单实现
- StaticListableBeanFactory - 简化版的BeanFactory,由于未实现BeanDefinitionRegistry,所以并不支持BeanDefinition的注册操作
- StubWebApplicationContext - WebApplicationContext的实现
- AbstractApplicationContext - ApplicationContext是应用的配置中的核心接口,应用运行过程中是只读的,但是可以通过实现其中的接口来达到reload的目的,AbstractApplicationContext是ApplicationContext的抽象类。相比于简单的BeanFactory,ApplicationContext能在类内部检查特定的bean的定义,这个类会自动注册BeanFactoryPostProcessor和BeanPostProcessors和ApplicationListeners
- AbstractBeanFactory - BeanFactory实现的一个抽象基类,我们重点研究。
在获取Bean时,首先要检查一下单例缓存,如果存在,直接根据缓存的Bean返回对象,如果不存在就走创建的逻辑。创建也要区分是单例还是Prototype。
源码很多,就直接看创建的主逻辑:
if (mbd.isSingleton()) {
// 匿名函数,调用一个抽象接口
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
Scope scope = (Scope)this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
this.beforePrototypeCreation(beanName);
Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
return var4;
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var23) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
}
}
} catch (BeansException var26) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var26;
}
}
最核心的就是创建Bean的过程。代码太多了,只能所个大改
它会调用实现createBean的子类:
AbstractAutowireCapableBeanFactory
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
}
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}
接着调用其doCreateBean,然后调用createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 获取 bean 对应的 class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 如果工厂方法不为空,则使用工厂方法创建
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 一个类有多个构造方法,带有不同的参数,所以调用前,需要根据参数解析出需要调用的构造方法,
// 这里使用了缓存,如果以前解析过构造方法,则在这里直接使用即可。
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 构造方法自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 默认构造方法自动注入
return instantiateBean(beanName, mbd);
}
}
// 解析构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造方法自动注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// 默认构造方法自动注入
return instantiateBean(beanName, mbd);
}
Bean的实例化要么通过反射,要么通过CGLib实现,但返回的不是代理对象,而是实例本身。
CglibSubclassingInstantiationStrategy
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
Class<?> subclass = this.createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass);
} else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
} catch (Exception var6) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", var6);
}
}
Factory factory = (Factory)instance;
factory.setCallbacks(new Callback[]{NoOp.INSTANCE, new CglibSubclassingInstantiationStrategy.LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), new CglibSubclassingInstantiationStrategy.ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
循环引用问题:
目前spring也只能解决单例的循环引用问题,在创建Bean的过程中会把其放进缓存中,那么在其他的对象也依赖他时,会首先去缓存拿到对象。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//首先直接检查缓存,看缓存是否存在
Object singletonObject = this.singletonObjects.get(beanName);
//如果没有,先查找正在创建的Bean,都在ObjectFactories中。
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
上面检查的过程,再看创建bean的过程,是需要把其放进Map中
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
Bean的生命周期先看一张图:
- IoC 容器对 Bean 进行实例化,上面也简要说了createBean的过程。
- 实例化完成后,如果该 bean 设置了一些属性的话,则利用 set 方法填充Bean属性。
- 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName() 方法。
- 如果 Bean 实现了 BeanClassLoaderAware 接口,则调用 setBeanClassLoader() 方法。
- 如果Bbean 实现了 BeanFactoryAware接口,则调用 setBeanFactory() 方法。
- 如果IoC注册了 BeanPostProcessor,则调用postProcessBeforeInitialization() 方法完成 bean 前置处理,BeanPostProcessor是在启动阶段注册到IoC容器中的;
- 如果该 bean 实现了 InitializingBean 接口,则调用 afterPropertiesSet() 方法,该部分不是对Bean对象本身的处理,只是增加了一些额外的逻辑;
- 如果该 bean 配置了 init-method 方法,则调用 init-method 指定的方法;
- 初始化完成后,如果该容器注册了 BeanPostProcessor 则会调用; postProcessAfterInitialization() 方法完成 bean 的后置处理;
- 对象完成初始化,开始方法调用;
- 在容器进行关闭之前,如果该 bean 实现了 DisposableBean 接口,则调用 destroy() 方法;
- 在容器进行关闭之前,如果该 bean 配置了 destroy-mehod,则调用其指定的方法。
参考资料:
spring-boot-2.0.3启动源码篇五 - run方法(四)之prepareContext
IoC-spring 的灵魂(带你轻松理解IOC思想及bean对象的生成过程)
Attack-spring-boot-3:深入理解 Application Context
SpringBoot源码分析之Spring容器的refresh过程
springboot源码中一窥BeanFactory接口getBean的实现
微信分享/微信扫码阅读