从下往上:Test→支持Junit测试
Core Container(Beans, Core, Context)→IOC
AOP, ASpects→ AOP
对象由原来程序本身创建,变成了程序接受对象;
层和层解耦分离,没有直接依赖关系;
bean: java对象
控制的内容: 谁来控制对象的创建(传统的应用程序对象的创建是由程序本身控制的,使用spring之后,由spring创建对象)
反转:程序本身创建对象,变为程序被动接受spring创建的对象。
IOC的实现是通过IOC容器实现的–BeanFactory
IOC创建对象的方式:
依赖:指bean对象的创建依赖于容器,Bean对象的依赖资源
注入:指bean对象依赖的资源由容器来设置和装配
Spring注入:
简化spring配置文件
scope | description |
---|---|
singleton(Default) | (默认)单例,整个容器(Spring bean容器)中只有一个对象实例 |
prototype | 原型,每次获取bean都产生一个新的对象 |
request | 每次HTTP请求时,新建一个对象,仅适用于基于Web的Spring ApplicationContext环境 |
session | 每次HTTP会话新建一个对象,仅适用于基于Web的Spring ApplicationContext环境 |
application | 一个ServletContext拥有一个对象,仅适用于基于Web的Spring ApplicationContext环境 |
websocket | 每次WebSocket新建一个对象,仅适用于基于Web的Spring ApplicationContext环境 |
Spring中的默认作用域;
在创建起容器时就同时自动创建了bean的对象,不管是否使用,都存在,而且每次获取到的对象都是同一个对象;
可以通过指定lazy-init="true"来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean;
优点:减少了新生成实例的消耗,减少jvm垃圾回收,可以快速获取到Bean
缺点:线程不安全
当看到这里的时候,很显然,会有一个疑问,既然Spring所有的bean默认都是单例的,那么是怎么保证线程安全的呢?
根据《深入理解JVM虚拟机》2.2.2节Java虚拟机栈
每个方法被执行的时候,Java虚拟机都 会同步创建一个栈帧[1](Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
每次执行方法时,都有自己的栈帧,这是线程隔离的;因此对于所有无状态单例都是线程安全的。
无状态:不会保存数据
有状态: 会保存数据
Prototype作用域的bean在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。
在创建容器时并没有实例化,只有当我们获取bean的时候才会去创建一个对象,而且每次获取到的对象都不是同一个。
因此,对于有状态的bean应该使用Prototype,无状态的bean可以使用Singleton。
Bean的生命周期概括:
以上总结的生命周期主要是 AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)类的doCreateBean方法
AbstractAutowireCapableBeanFactory.java 展开源码
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.实例化
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 属性填充
populateBean(beanName, mbd, instanceWrapper);
// 初始化
// 完成属性依赖注入后,进一步初始化Bean
// 具体进行了以下操作:
// 1.若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象
// 2.遍历后置处理器,调用实现的postProcessBeforeInitialization方法,
// 3.如果实现了initialzingBean,调用实现的 afterPropertiesSet()
// 4.如果配置了init-mothod,调用相应的init方法
// 5.遍历后置处理器,调用实现的postProcessAfterInitialization
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
// 如果符合 bean 的销毁条件,则执行单例bean 的销毁工作
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
initializeBean 展开源码
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 执行Aware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化前BeanPostProcessors
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 初始化
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化后BeanPostProcessors
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
1、首先思考一个问题,既然说Spring大部分都是单例,只要不是懒加载的单例,在容器启动后就自动创建了,那是什么时候创建的?
在该方法上打断点,查看调用栈可以发现,main方法开始后,层层调用,在AbstractApplicationContext类的refresh()方法里面:
|
然后调用到doCreateBean();
Demo实现测试:
Demo
|
配置类
|
测试代码
|
运行测试代码,可以看到输出:
可以看到符合生命周期的轨迹。
以上是一个单例bean的生命周期,将bean的type改成prototype,可以发现当容器关闭时,作为prototype作用域的bean,predestroy方法和destroy方法都没有被调用,spring不对prototype bean的整个生命周期负责。
待解决的问题:
参考
1.
2.