spring创建对象的过程(生命周期)

在还没使用spring框架的时候,我们创建对象的时候方式

1.类的反射

2.new

3.instance

代码比较重复而且一些必须创建的对象,比如说业务层都需要创建,dao层也需要创建,这样导致我们重复操作了这些事情

但是spring容器可以帮我们处理这些繁琐的事情,而且还能加强(具体如何加强后面说到)

spring得益于它的IOC和AOP,大大减少我们的琐碎事情

下面就来聊聊spring如何帮我们创建对象的!!

spring创建对象流程

主要围绕refresh方法讲解,一下是spring官方下载的源码,翻译是参考尚硅谷的添加上去的

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
             //1 刷新前的预处理
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
             //2 获取BeanFactory;刚创建的默认DefaultListableBeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
            //3 BeanFactory的预准备工作(BeanFactory进行一些设置)
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
                 // 4 BeanFactory准备工作完成后进行的后置处理工作;
                 // 4.1)、抽象的方法,当前未做处理。子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置
				postProcessBeanFactory(beanFactory);

				 /**************************以上是BeanFactory的创建及预准备工作  ****************/
                
                // 5 执行BeanFactoryPostProcessor的方法;
//BeanFactoryPostProcessor:BeanFactory的后置处理器。在BeanFactory标准初始化之后执行的;
//他的重要两个接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
                invokeBeanFactoryPostProcessors(beanFactory);
​
                //6 注册BeanPostProcessor(Bean的后置处理器)
                registerBeanPostProcessors(beanFactory);
​
            // 7 initMessageSource();初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
                initMessageSource();
​
                // 8 初始化事件派发器
                initApplicationEventMulticaster();
​
                // 9 子类重写这个方法,在容器刷新的时候可以自定义逻辑;
                onRefresh();
​
                // 10 给容器中将所有项目里面的ApplicationListener注册进来
                registerListeners();
       
​
                // 11.初始化所有剩下的单实例bean;
                finishBeanFactoryInitialization(beanFactory);
​
                // 12.完成BeanFactory的初始化创建工作;IOC容器就创建完成;
                finishRefresh();
            }
​
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
​
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
​
                // Reset 'active' flag.
                cancelRefresh(ex);
​
                // Propagate exception to caller.
                throw ex;
            }
​
            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

1.启动application,执行invokeBeanFactoryPostProcessors(后置工厂处理器)扫描该app下的所有路径的class的注解,controller,service,dao,reporisity,compoment,aspect等注解(还有很多)并且放进一个集合

2.执行invokeBeanDefinitionRegistryPostProcessors,遍历集合并且生成beandefinition对象,并且进行后续的加强处理,是否含有@lazy注解,@scope注解等,然后存放在一个beanDefinitionMap里(这里的beandefinition对象里是含有该扫描到的类的class)

3.遍历beanDefinitionMap验证bd对象,并且执行finishBeanFactoryInitialization方法中完成了bean的实例化,调用createBeanInstance完成了推断构造方法和实例化(newInstance,注意此时是实例化,对象属性没注入,还是null的对象,Aware接口的方法没有调用,@PostConstruct方法也没有调用,再一次说明他不是一个完整的bean,继而applyMergedBeanDefinitionPostProcessors方法就是用来处理合并后的beanDefinition对象)

4.判断是否支持循环依赖,如果支持则提前暴露一个工厂对象执行addSingletonFactory。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5rOi5rOi5ZWK,size_20,color_FFFFFF,t_70,g_se,x_16 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5rOi5rOi5ZWK,size_20,color_FFFFFF,t_70,g_se,x_16

 5.spring会判断是否需要完成属性注入,执行populateBean,里面有判断是否需要注入,如果需要注入用哪种方式,注入方式后面会写一遍文章

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5rOi5rOi5ZWK,size_20,color_FFFFFF,t_70,g_se,x_16

循环依赖也在这个方法里面完成的。该方法里面调用了一个非常重要的方法 doGetBean的方法 (Spring解决循环依赖的方式)

 先留意一下这个三个map,解决循环依赖的中间缓存,后面会说到

 

 接下来看一下从map获取对象的过程

	/**
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference whether early references should be created or not
	 * @return the registered singleton object, or {@code null} if none found
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //从一级缓存里获取bean
		Object singletonObject = this.singletonObjects.get(beanName);
        //如果这个时候是x注入y,创建y,y注入x,获取x的时候那么x不在容器,具体请查看上面的图addSingletonFactory,此时的x是放在singletonFactory
		//第一个singletonObject == null成立
		//第二个条件判断是否存在正在创建bean的集合当中,正在创建的bean会先放在一个singletonsCurrentlyInCreation里,成立
		//进入if分支
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //先从三级缓存那x?为什么先从三级缓存拿?
            //为什么要从三级缓存里拿?在这个方法明明是put到factory二级缓存里去了addSingletonFactory,所以这里的singletonObject==null,allowEarlyReference先不说,是true,所以进入分支
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
                    //1.1
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
                    //1.1和这一行之所以这样写是加快性能,第一次判断不上锁,第二次判断才上锁,判断相同的条件,类似于单例模式
						if (singletonObject == null) {
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
                    从二级缓存中获取一个 singletonFactory,回顾前文,能获取到
					//由于这里的beanName=x,故而获取出来的工厂对象,能产生一个x半成品状态bean(属性还没注入,或者注入了一部分)
								singletonObject = singletonFactory.getObject();
                                //拿到了半成品的xbean之后,把他放到三级缓存;
								this.earlySingletonObjects.put(beanName, singletonObject);                
                            //然后从二级缓存清除掉x的工厂对象;
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

然后这里是上升为一级缓存

/**
	 * Return the (raw) singleton object registered under the given name,
	 * creating and registering a new one if none registered yet.
	 * @param beanName the name of the bean
	 * @param singletonFactory the ObjectFactory to lazily create the singleton
	 * with, if necessary
	 * @return the registered singleton object
	 */
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
                    //上升为一级缓存
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

6. 至此一个bean完成初始化,被put到单例池,这说明一个bean在spring容器当中被创建出来是有一个过程的,这个过程就是所谓的bean的生命周期,我们的循环依赖也是在这个生命周内完成的。

最后附上简单的图

aaa4d71f5c0a486587e4411d84dc23f2.png

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring IOC 控制反转:把创建对象的权利交给Spring 创建对象 1.无参构造<bean class=""> 2.静态工厂<bean class="" factory-method=""> 3.实例工厂 <bean bean-factory="" factory-method=""> 管理对象 对象关系DI 构造器注入<construct-arg> set注入<property> 生命周期 scope:prototype/singleton init-method destroy-method API BeanFactory:使用这个工厂创建对象的方式都是懒加载,在调用的时候再创建 ClassPathXmlApplicationContext:使用这个工厂创建对象,他会根据scope智能判断是否懒加载,如果是单例则创建容器时就会创建里面bean的实例,如果是多例在获取使用时才会创建bean实例 FileSystemXmlApplicationContext磁盘路径 AnnotationConfigApplicationContext注解 WebApplicationContext:web环境使用的容器 注解 创建对象 Component:不分层的注解 Controller:web层 Service:service层 Repository:dao层 管理对象 注入 AutoWired Qualifier Resource Value 声明周期 Scope PostConstruct PreDestroy 新注解 Bean:写方法上,将方法的返回值 Configuration:标记配置类 ComponentScan包扫描 PropertySource:加载配置文件 Import:导入其他配置类 AOP 概念:面向切面编程,在不改变源码的情况下对方法进行增强,抽取横切关注点(日志处理,事务管理,安全检查,性能测试等等),使用AOP进行增强,使程序员只需要关注与业务逻辑编写. 专业术语 目标Target:需要增强的类 连接点JoinPoint:目标中可被增强的方法 切入点PointCut:被增强的方法 增强Advice:增强代码 切面Aspect:切点加通知 织入weaving:讲切面加载进内存形成代理对象过程 代理Proxy 底层实现 JDK动态代理(默认) 基于接口:代理对象与目标对象是兄弟关系,目标类必须实现接口 CGLIB动态代理 基于父类:代理对象与目标对象是父子关系.目标不能被final修饰 修改默认代理方法:<aop:aspectj-autoproxy proxy-target-class="true"/> 增强种类 前置通知 后置通知 异常通知 最终通知 环绕通知 注意:使用注解的方式,最终通知和后置通知顺序换了,建议使用环绕通知 注解 配置 声明式事务管理 PlatFormTransactionManager:平台事务管理器:定义了commit/rollback Mybatis/jdbc:DataSourceTransactionManager Hibernater:HibernaterTransactionManager TransactionManagerDifinition 传播行为:A-->B,在B上声明是否一定需要事务管理 requerd:必须的(默认),如果A有事务那么就加入A的事务,如果A没有事务那么单独创建一个事务 supports,如果A有事务则加入,如果没有就算了 隔离级别 default:使用数据库默认的隔离级别(mysql:可重复读,oracle:读已提交) readuncommited:读未提交,不可以解决任何问题 readcommited:读已提交,可以解决脏读问题 repeatableRead:可重复读,可以解决脏读,不可重复读问题 Serializbler:串行化,可以解决所有问题 超时时间: 默认-1(永不超时),事务一直不提交也不回滚的时间 是否只读: 默认false TransactionManagerStatus: 事务的一些状态 整合 Spring整合Junit 1.导入依赖spring-test 2.加注解:RunWith、ContextConfiguration 3.注入对象进行测试 Spring整合web 1.导入依赖spring-web 2.配置ContextLoadListener 3.配置 <!--全局初始化参数--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> 4.在Servlet中使用WebApplicationContextUtils获取容器对象 5.使用容器对象去获取Service对象

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值