作者:x1aoda1

https://www.cnblogs.com/darope/p/13917264.html

1.1 Spring测试环境搭建

Spring模块概览,绿色是模块,Spring中八大模块,黑色表示该模块包含的jar包(组件)。例如我们想要用IOC容器,也就是绿色的CoreContainer,我们需要导入Beans,Core,Context,SpEL(spring-expression)四个包。

Spring模块概览
  • Test:测试相关

  • Core Container:IOC容器

  • AOP:面向切面编程

  • Aspects:切面

  • Instrumenttation:跟JDK关联,一般不用

  • Messaging:消息服务,一般不用

  • Data Access/Integration:数据访问与集成(JDBC访问,Transaction事务,ORM对象关系映射,OXM和XML映射一般不用,JMS为Java消息服务Java-message-service一般不用)

  • Web:Web服务(WebSocket网络通信协议,Servlet, Web,Portlet一般不用)

最偷懒的方式,是直接导入Spring-Framework。但是可能导入不必要的包,导致项目打包后比较大

由于Spring-Content中的ApplicationContent是整个IOC的入口。我们导入Spring-context包即可

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.3.RELEASE</version>
</dependency>

我们导入spring-content后,默认会导入该组件的依赖jar,spring-content底层的依赖可以看到,实际上我们是导入了Core Container模块:

  <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.2.3.RELEASE</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.3.RELEASE</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.3.RELEASE</version><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>5.2.3.RELEASE</version><scope>compile</scope></dependency></dependencies>

新建Spring配置文件spring.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--注册一个对象,spring回自动创建这个对象--><!--一个bean标签就表示一个对象id:这个对象的唯一标识class:注册对象的完全限定名--><bean id="hello" class="com.xiaodai.service.Hello"><!--使用property标签给对象的属性赋值name:表示属性的名称value:表示属性的值--><property name="id" value="1"></property><property name="name" value="zhangsan"></property><property name="age" value="18"></property></bean>
</beans>

编写测试类:

import com.xiaodai.service.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Hello hello = applicationContext.getBean("hello", Hello.class);System.out.println(hello.getName());}}

1.2 Debug容器创建过程

从测试类的new ClassPathXmlApplicationContext("spring.xml")开始debug,进入ClassPathXmlApplicationContext,可以看到:

 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {super(parent);// 设置配置文件路径setConfigLocations(configLocations);if (refresh) {// 核心步骤refresh();}}

加载配置文件后,进入refresh()方法,该方法是容器初始化的核心步骤。该方法包含十三个方法:

        @Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing./** * 准备刷新,做一些最基本的准备化工作**/prepareRefresh();// Tell the subclass to refresh the internal bean factory./** * 获得一个刷新的bean容器,实质就是获取工厂。* 加载xml等配置文件,用该文件产生的BeanDefinition来创建一个工厂**/ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context./*** 准备bean工厂**/prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.// 后置增强,方便扩展postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.// 实例化并且执行BeanFactoryPostProcessorsinvokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// 实例化并且注册所有的BeanPostProcessorregisterBeanPostProcessors(beanFactory);// Initialize message source for this context.// 国际化设置,一般用不到initMessageSource();// Initialize event multicaster for this context.// 初始化应用程序的多波器和广播器initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.// 空方法,预留给子类做扩展onRefresh();// Check for listener beans and register them.// 注册监听器registerListeners();// Instantiate all remaining (non-lazy-init) singletons.// 工作中常用,面试常问。实例化所有非懒加载的实例对象finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.// 完成刷新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.3 AbstractApplicationContext的refresh()包含的13个方法分析

结合概览图一个一个方法分析:

Bean工厂实例化Bean概览图

方法1:prepareRefresh() => 准备工作

准备刷新,做一些最基本的准备化工作

 protected void prepareRefresh() {// Switch to active.// 设置开始时间this.startupDate = System.currentTimeMillis();// 关闭状态设置为falsethis.closed.set(false);// 活跃状态设置为truethis.active.set(true);// 打印日志if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);}else {logger.debug("Refreshing " + getDisplayName());}}// Initialize any placeholder property sources in the context environment.// 初始化属性资源initPropertySources();// Validate that all properties marked as required are resolvable:// see ConfigurablePropertyResolver#setRequiredProperties// 获取环境信息,验证属性信息getEnvironment().validateRequiredProperties();// Store pre-refresh// 存储预刷新的一些应用信息的监听器ApplicationListeners...if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);}else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// Allow for the collection of early ApplicationEvents,// to be published once the multicaster is available...// 创建一些监听器事件的集合this.earlyApplicationEvents = new LinkedHashSet<>();}

总结:1.设置启动事件 2.设置关闭活跃的状态 3.获取环境对象并设置属性值 4.设置监听器以及需要发布事件的集合

重要的点:

  • 获取环境信息,验证属性信息,getEnvironment().validateRequiredProperties();

  • 存储预刷新的一些应用信息的监听器,在Spring中是空实现,但是SpringBoot中,是有具体的值的

方法2:obtainFreshBeanFactory() => 获得一个刷新的bean容器

获得一个刷新的bean容器,实质就是获取工厂。创建容器对象DefaultListableBeanFactory;加载xml配置文件的属性到当前的工厂中,最重要的就是BeanDefinition

Bean工厂实例继承关系图

AbstractRefreshableApplicationContext:

    // 只要进到这个方法,那么我们创建的一定是一个新的工厂@Overrideprotected final void refreshBeanFactory() throws BeansException {if (hasBeanFactory()) {// 如果存在先销毁,后关闭destroyBeans();closeBeanFactory();}try {// 创建bean工厂,这里使用的就是DefaultListableBeanFactory。此时创建的工厂里面的属性值都是默认值DefaultListableBeanFactory beanFactory = createBeanFactory();// 序列化idbeanFactory.setSerializationId(getId());// 设置一些属性值customizeBeanFactory(beanFactory);// 加载bean的定义属性值。该方法有很多重载,非常复杂,核心是do操作// 完成配置文件或者配置类文件的加载loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}

方法3:prepareBeanFactory(beanFactory) => 准备(初始化)Bean工厂

为方法2拿到的工厂,设置某些具体的值

 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context's class loader etc.// 为bean工厂设置类加载器beanFactory.setBeanClassLoader(getClassLoader());// 设置SPEL解析器beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.// 添加一个BeanPostProcessorbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 忽略对应接口的实现beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);// BeanFactory interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.// 注册一些依赖beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// Register early post-processor for detecting inner beans as// ApplicationListeners添加一个BeanPostProcessor增强器ApplicationListeners.beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// Register default environment beans.if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}}

方法4:postProcessBeanFactory(beanFactory) => 后置增强Bean(扩展实现)

空方法,方便扩展

方法5:invokeBeanFactoryPostProcessors(beanFactory) => 执行BFPP

实例化并且执行BeanFactoryPostProcessors

 /*** Instantiate and invoke all registered BeanFactoryPostProcessor beans,* respecting explicit order if given.* <p>Must be called before singleton instantiation.* 单例对象之前一定调用,因为单例bean创建后就只有一份*/protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}

方法6:registerBeanPostProcessors(beanFactory) => 注册BPP

实例化并且注册所有的BeanPostProcessor。实例化Bean之前的准备工作

 /*** Instantiate and register all BeanPostProcessor beans,* respecting explicit order if given.* <p>Must be called before any instantiation of application beans.*/protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);}

方法7:initMessageSource() => 国际化设置

方法8:initApplicationEventMulticaster() => 初始化应用程序的多波器和广播器

也属于准备工作

方法9:onRefresh() => 预留给子类做扩展

空方法

方法10:registerListeners() => 注册监听器

也属于准备工作

 /*** Add beans that implement ApplicationListener as listeners.* Doesn't affect other listeners, which can be added without being beans.*/protected void registerListeners() {// Register statically specified listeners first.for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let post-processors apply to them!String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}// Publish early application events now that we finally have a multicaster...Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}

方法11:finishBeanFactoryInitialization(beanFactory) => 实例化所有单例对象

面试常问,工作常用。过程比较复杂

 /*** Finish the initialization of this context's bean factory,* initializing all remaining singleton beans.*/protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context./*** 把类型转化操作,设置到当前的beanFactory里面去**/if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values./*** 判断当前的beanFactory有没有内置的值处理器**/if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early./*** 织入Aware**/String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.// 设置类加载器beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes./*** 冻结:某些bean不需要进行修改操作了,放入**/beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons./*** 实例化所有非懒加载的实例对象(重要)**/beanFactory.preInstantiateSingletons();}

实例化所有非懒加载的实例对象方法:

 @Overridepublic void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine./*** 拿到所有注册bean的名称**/List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...// 循环去创建我们需要的单例对象for (String beanName : beanNames) {// 拿到bean的定义信息,就是我们在xml配置文件里面指定的一些属性RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 是否是抽象的,是否是单例的,是否是懒加载的if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 判断当前类是否实现了factoryBean接口。一般没实现,直接进入下面的getBeanif (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {// 通过beanName。拿到beangetBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}}

重要方法:

  • getMergedLocalBeanDefinition

 /*** Return a merged RootBeanDefinition, traversing the parent bean definition* if the specified bean corresponds to a child bean definition.* @param beanName the name of the bean to retrieve the merged definition for* @return a (potentially merged) RootBeanDefinition for the given bean* @throws NoSuchBeanDefinitionException if there is no bean with the given name* @throws BeanDefinitionStoreException in case of an invalid bean definition*/// 返回一个合并好的RootBeanDefinition。整合子类和父类protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {// Quick check on the concurrent map first, with minimal locking.RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);if (mbd != null && !mbd.stale) {return mbd;}return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));}
  • getBean() => doGetBean()

 /*** Return an instance, which may be shared or independent, of the specified bean.* @param name the name of the bean to retrieve* @param requiredType the required type of the bean to retrieve* @param args arguments to use when creating a bean instance using explicit arguments* (only applied when creating a new instance as opposed to retrieving an existing one)* @param typeCheckOnly whether the instance is obtained for a type check,* not for actual use* @return an instance of the bean* @throws BeansException if the bean could not be created*/@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 获取beanNamefinal String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.// 单例检查,如果一级,二级,三级缓存中存在该Bean,直接获取到了Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.// 如果是单例对象的话,尝试解决循环依赖问题if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.// 获取父类容器BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}// 标志位。如果不是类型检查,表示要创建bean,此处在集合中做一个记录if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {// 获取beanDefinitionfinal RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检测beanDefinitioncheckMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 检查当前的bean是否有其他依赖的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// 如果有依赖的bean,我们要先递归解决其他依赖的beanfor (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.// 是否是单例的if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();final 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, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {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",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// Check if required type matches the type of the actual bean instance.if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}
  • getSingleton

 /*** 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 {// 实际上就是调用了CreateBeansingletonObject = 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;}}
  • doCreateBean => 通过上方法的singletonObject = singletonFactory.getObject();进入的

 /*** 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(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {/*** 核心的创建实例化Bean的过程**/instanceWrapper = createBeanInstance(beanName, mbd, args);}final 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 {/*** 填充属性,上文的实例化只是默认属性值。填充属性是初始化的第一步,第二步是执行init方法**/populateBean(beanName, mbd, instanceWrapper);/*** 执行init方法**/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 " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {/*** 需要销毁的时候,销毁的钩子函数**/registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

面试题:为甚么循环依赖的解决要使用三级缓存?

  • createBeanInstance => 核心的创建和实例化bean的过程,由doCreateBean调用

大量的反射出现在该方法中,用来创建对象

 /*** Create a new instance for the specified bean, using an appropriate instantiation strategy:* factory method, constructor autowiring, or simple instantiation.* @param beanName the name of the bean* @param mbd the bean definition for the bean* @param args explicit arguments to use for constructor or factory method invocation* @return a BeanWrapper for the new instance* @see #obtainFromSupplier* @see #instantiateUsingFactoryMethod* @see #autowireConstructor* @see #instantiateBean*/protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// Make sure bean class is actually resolved at this point.Class<?> beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...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);}}// Candidate constructors for autowiring?// 构造器Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// No special handling: simply use no-arg constructor./*** 默认无参构造**/return instantiateBean(beanName, mbd);}
  • instantiateBean(beanName, mbd) => 默认无参构造

 /*** Instantiate the given bean using its default constructor.* @param beanName the name of the bean* @param mbd the bean definition for the bean* @return a BeanWrapper for the new instance*/protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {try {Object beanInstance;final BeanFactory parent = this;if (System.getSecurityManager() != null) {beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->// 实例化只会分配内存空间,设置默认值getInstantiationStrategy().instantiate(mbd, beanName, parent),getAccessControlContext());}else {beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);}BeanWrapper bw = new BeanWrapperImpl(beanInstance);initBeanWrapper(bw);return bw;}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);}}
  • instantiate

 @Overridepublic Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.if (!bd.hasMethodOverrides()) {Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Class<?> clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);}else {constructorToUse = clazz.getDeclaredConstructor();}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}return BeanUtils.instantiateClass(constructorToUse);}else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);}}
  • BeanUtils.instantiateClass => 通过构造器反射创建bean

 /*** Convenience method to instantiate a class using the given constructor.* <p>Note that this method tries to set the constructor accessible if given a* non-accessible (that is, non-public) constructor, and supports Kotlin classes* with optional parameters and default values.* @param ctor the constructor to instantiate* @param args the constructor arguments to apply (use {@code null} for an unspecified* parameter, Kotlin optional parameters and Java primitive types are supported)* @return the new instance* @throws BeanInstantiationException if the bean cannot be instantiated* @see Constructor#newInstance*/public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {Assert.notNull(ctor, "Constructor must not be null");try {ReflectionUtils.makeAccessible(ctor);if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {return KotlinDelegate.instantiateClass(ctor, args);}else {Class<?>[] parameterTypes = ctor.getParameterTypes();Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");Object[] argsWithDefaultValues = new Object[args.length];for (int i = 0 ; i < args.length; i++) {if (args[i] == null) {Class<?> parameterType = parameterTypes[i];argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);}else {argsWithDefaultValues[i] = args[i];}}return ctor.newInstance(argsWithDefaultValues);}}catch (InstantiationException ex) {throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);}catch (IllegalAccessException ex) {throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);}catch (IllegalArgumentException ex) {throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);}catch (InvocationTargetException ex) {throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());}}

方法12:finishRefresh() => 完成刷新

 /*** Finish the refresh of this context, invoking the LifecycleProcessor's* onRefresh() method and publishing the* {@link org.springframework.context.event.ContextRefreshedEvent}.*/protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).// clearResourceCaches();// Initialize lifecycle processor for this context.initLifecycleProcessor();// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();// Publish the final event.publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);}

方法13:resetCommonCaches() => 缓存重置

 /*** Reset Spring's common reflection metadata caches, in particular the* {@link ReflectionUtils}, {@link AnnotationUtils}, {@link ResolvableType}* and {@link CachedIntrospectionResults} caches.* @since 4.2* @see ReflectionUtils#clearCache()* @see AnnotationUtils#clearCache()* @see ResolvableType#clearCache()* @see CachedIntrospectionResults#clearClassLoader(ClassLoader)*/protected void resetCommonCaches() {ReflectionUtils.clearCache();AnnotationUtils.clearCache();ResolvableType.clearCache();CachedIntrospectionResults.clearClassLoader(getClassLoader());}

最后回顾整个流程概览图:

Bean工厂实例化Bean概览图

  • 面试官:String长度有限制吗?是多少?还好我看过

  • SpringBoot 的jar包为什么可以直接运行?

  • 一份 Spring Boot 项目搭建模板

  • Maven虐我千百遍,我待Maven如初恋!

  • MySQL面试高频100问(工程师方向)

  • 亲身经历:一次sql缺少where条件的惨案…

  • 基于netty手写Tomcat


好文章,我在看

Spring创建Bean的全过程Debug,没人能说的这么通透了相关推荐

  1. 通过Debug带你详细了解Spring创建Bean的过程,一清二楚!

    Spring流程Debug 1.1 Spring测试环境搭建 Spring模块概览,绿色是模块,Spring中八大模块,黑色表示该模块包含的jar包(组件).例如我们想要用IOC容器,也就是绿色的Co ...

  2. Spring源码系列(十二)Spring创建Bean的过程(二)

    1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...

  3. Spring创建Bean的3种方式

    1. Spring创建Bean的三种方式 1. 调用构造器(因为常用就不讲) 2. 调用静态工厂方法 3. 调用实例工厂方法 2. 使用静态工厂方法 1.此时<bean.../>元素要指定 ...

  4. Spring创建Bean的基本步骤

    最简单的spring创建Bean主要分为以下几个步骤: 加载Class类 调用构造方法 设置属性 回调Aware(BeanNameAware, BeanFactoryAware) 回调初始化方法(In ...

  5. Spring5——(一)spingIOC(入门介绍,spring创建bean,依赖,注入,注解方式)

    为什么要有框架? (1)对于web层来说,一个大型的程序往往需要编写大量的servlet,并且取值封装会非常繁琐. (2)对于dao层,要编写大量的sql语句,对于结果的解析也很麻烦,并且sql的复用 ...

  6. spring创建bean模式singleton与prototype的区别

    spring 创建bean有单例模式(singleton)和原始模型模式(prototype)这两种模式. 在默认的情况下,Spring中创建的bean都是单例模式的(注意Spring的单例模式与Go ...

  7. Spring创建Bean的三种方式的使用和区别

    在学习Spring的时候,发现Spring的IOC(控制反转)为我们提供的三种创建Bean的方式. 1.Spring创建Bean的三种方式 这里采用XML配置,分别演示三种创建Bean的方式和代码. ...

  8. Spring 创建Bean的三种方式

    创建Bean的三种方式 第一种方式:使用默认构造函数创建. 在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时.采用的就是默认构造函数创建bean对象,此 ...

  9. Spring创建Bean的流程

    大致步骤 简单来说:Bean会经历四个阶段: 实例化–>属性赋值–>初始化–>销毁 具体来说: 实例化:new xxx():有两个时候会触发实例化: 像容器申请一个Bean的时候 当 ...

最新文章

  1. 有关于Matlab的regionprops函数的PixelIdxList和PixelList的一点解释
  2. 斜率小于0的连线数量 51Nod - 1107 (树状数组+离散化)
  3. python好用-Python里三个好用的调试神器
  4. 开始学习Solaris
  5. desktop docker 无法卸载_docker,生信人的福音!
  6. bootstrap 打印组件_创想三维:有了3D打印机,后期该如何维护呢-创想三维 Ender-1_深圳3D打印机行情...
  7. php百度编辑器精简版,开源web编辑器|百度编辑器ueditor下载1.4.3.4php版 下载_久友软件下载...
  8. python模块补充
  9. 红外遥控c语言,NEC协议红外遥控器
  10. 《C程序员从校园到职场》一2.2 破除错误观念
  11. 手机照片×××作:千里走单骑
  12. Gym - 101142F Folding(折半)
  13. pcl_viewer 常用实用指令
  14. 备案网站建设方案书模板
  15. 智能小车-红外循迹篇
  16. 目标检测算法之CVPR 2019 Guided Anchoring
  17. mysql 文本挖掘_GitHub - HuiHuiT/dianping_textmining: 大众点评评论文本挖掘,包括点评数据爬取、数据清洗入库、数据分析、评论情感分析等的完整挖掘项目...
  18. 三星 android 4.4.4,我的手机是三星4.4.4安卓系统,怎么升级到6.1版本
  19. c语言已知加速度求位移速度,已知初速度,加速度,时间,求位移
  20. jqurey常用方法(jqurey设计思想)

热门文章

  1. java、python、node等,轻松获取驾考题库数据
  2. case when then end用法
  3. oracle10g配置远程连接
  4. nvidia jeston 设备树使能SPI
  5. 快来看看搜索引擎到底是怎么工作的吧!
  6. 知识数据大爆炸,爱数如何抢滩?
  7. Microsoft.Practices.Unity依赖注入使用实例
  8. springboot 连接sqlite
  9. Android 官方数据库Room --- 配置
  10. Android 数据库操作:Room