作者:x1aoda1

来源: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());}

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

回复「进群」即可进入无广告技术交流群。同时送上250本电子书+学习视频作为见面
有你想看的精彩 徒手撸了一个API网关,理解更透彻了,代码已上传github,自取~
【收藏】神器 Nginx 的学习手册
总结零散的 MySQL 基础知识
教你玩转 统一异常处理
VS Code真的会一统江湖吗?
牛啊!全球当下最厉害的 14 位程序员
炸了!炸了!微信十周年炸裂更新(附安卓版)
Springboot + Vue + shiro 实现前后端分离、权限控制
JetBrains遭美国调查!
微服务架构 - Gateway网关限流
目前5000+ 人已关注加入我们爱点赞的人,运气都不会太差

一文搞定 Spring Bean 的创建全过程!相关推荐

  1. 一文搞定 Spring Data Redis 详解及实战

    转载自  一文搞定 Spring Data Redis 详解及实战 SDR - Spring Data Redis的简称. Spring Data Redis提供了从Spring应用程序轻松配置和访问 ...

  2. 11 张流程图帮你搞定 Spring Bean 生命周期 (核心)

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:腾讯推出高性能 RPC 开发框架 个人原创100W+访问量博客:点击前往,查看更多 来源:www.jianshu ...

  3. 一文搞定Spring及IOC,给你总结的清新脱俗!

    Spring及IOC介绍 Spring简介 Rod Johnson,Spring Framework创始人,著名作者.很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然 ...

  4. 一文搞定 Spring Security 异常处理机制!

    今天来和小伙伴们聊一聊 Spring Security 中的异常处理机制. 在 Spring Security 的过滤器链中,ExceptionTranslationFilter 过滤器专门用来处理异 ...

  5. 一文搞定Swing和Qt按钮和文本框的创建

    一文搞定Swing和Qt按钮和文本框的创建 Qt的截图 java的 源码 package com.lujun;import java.awt.Container;import javax.swing. ...

  6. 【嵌入式开发-AD19】六文搞定Altium Designer-第一章:AD介绍及原理图库的创建

    [嵌入式开发-AD19]六文搞定Altium Designer-第一章:AD介绍及原理图库的创建 在文章的开头我想首先简单介绍一下国产全免费EDA软件,嘉立创EDA.嘉立创EDA拥有网页版和安装版两种 ...

  7. 一文搞定vim,从安装到入门到精通,助你成功入门vim

    一文搞定vim,从安装到入门到精通 NO.1 闲聊 NO.2 安装(不是重点!觉得这部分讲的不清楚可以去找一篇win下安装vim的文章来看,然后跳去NO.3接着看) NO3. 文章核心重点-vim使用 ...

  8. 一文搞定面试中的二叉树问题

    一文搞定面试中的二叉树问题 版权所有,转载请注明出处,谢谢! http://blog.csdn.net/walkinginthewind/article/details/7518888 树是一种比较重 ...

  9. 一文搞定Matplotlib 各个示例丨建议收藏

    摘要:Matplotlib 是 Python 的绘图库. 它可与 NumPy 一起使用 ,Matplotlib也是深度学习的常用绘图库,主要是将训练的成果进行图形化,因为这样更直观,更方便发现训练中的 ...

最新文章

  1. 计算机视觉系列最新论文(附简介)
  2. java 挂钩子_挂钩组件
  3. 重学 html の meta 标签
  4. Java Stringbuilder简单介绍
  5. SQL基础整理——例题
  6. ssh-copy-id不生效问题
  7. 【Pytorch神经网络理论篇】 26 基于空间域的图卷积GCNs(ConvGNNs):定点域+谱域+图卷积的操作步骤
  8. leetcode - 1039. 多边形三角剖分的最低得分
  9. “一张图”解释特色小镇发展历程
  10. java的smalltalk规则,Smalltalk相当于Java的静态是什么?
  11. oracle v$context,30.Oracle杂记——Oracle常用动态视图v$session
  12. python新手如何编写一个猜数字小游戏
  13. 计算机考试一级b软件未来教育,2019.9全国计算机一级MS Office考试每日一练
  14. 给老年人“种草”,是不是一门好生意?
  15. js 华氏/摄氏转换
  16. CSS3 制作 3D 水晶糖果按钮
  17. 电商系统,商品属性表和功能设计,可用于各种实体的属性
  18. 这里有一个url=https://www/.baidu.com/s?id=111name=yourname,写一个函数获取query的参数和值存放在一个对象...
  19. 机械键盘连击问题的软件解决方案
  20. 本地系统服务例程:Nt和Zw系列函数

热门文章

  1. 安装程序集组件{0D7E67F6-1A6A-3A26-AF95-B8E83DDCCC3F}时出错。HRESULT:0x80070005。 解决办法
  2. C#设计一个简单的计算器,实现两个数的加减乘除和求幂等计算
  3. android 中添加 Google Play Game Services 功能 1
  4. STM32入门必看 简单几步用cubeMX模拟声控灯
  5. 谈华为造车,余承东的葫芦卖的什么药?
  6. 2022N1叉车司机考试题库模拟考试平台操作
  7. 计算机仿真技术相关论文,计算机仿真技术论文.doc
  8. 金蝶KIS 引出数据WPS EXCEL 空白 所见即所得引出空白 电脑上安装了WPS 不想卸载 引出的时候用Office也是空表
  9. OA系统横评:OA市场运营推广详解
  10. cncf,ddd,kong,zookeeper,k8s,ectd,docker,hbase,kafka,rocketmq,lua