赞
踩
从下往上:Test→支持Junit测试
Core Container(Beans, Core, Context)→IOC
AOP, ASpects→ AOP
对象由原来程序本身创建,变成了程序接受对象;
层和层解耦分离,没有直接依赖关系;
bean: java对象
控制的内容: 谁来控制对象的创建(传统的应用程序对象的创建是由程序本身控制的,使用spring之后,由spring创建对象)
反转:程序本身创建对象,变为程序被动接受spring创建的对象。
IOC的实现是通过IOC容器实现的–BeanFactory
IOC创建对象的方式:
依赖:指bean对象的创建依赖于容器,Bean对象的依赖资源
注入:指bean对象依赖的资源由容器来设置和装配
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.Introduction to the Spring Framework
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。