Spring创建Bean的全过程Debug,没人能说的这么通透了
作者:x1aoda1
https://www.cnblogs.com/darope/p/13917264.html
1.1 Spring测试环境搭建
Spring模块概览,绿色是模块,Spring中八大模块,黑色表示该模块包含的jar包(组件)。例如我们想要用IOC容器,也就是绿色的CoreContainer,我们需要导入Beans,Core,Context,SpEL(spring-expression)四个包。
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个方法分析
结合概览图一个一个方法分析:
方法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
”
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());}
最后回顾整个流程概览图:
面试官:String长度有限制吗?是多少?还好我看过
SpringBoot 的jar包为什么可以直接运行?
一份 Spring Boot 项目搭建模板
Maven虐我千百遍,我待Maven如初恋!
MySQL面试高频100问(工程师方向)
亲身经历:一次sql缺少where条件的惨案…
基于netty手写Tomcat
好文章,我在看
Spring创建Bean的全过程Debug,没人能说的这么通透了相关推荐
- 通过Debug带你详细了解Spring创建Bean的过程,一清二楚!
Spring流程Debug 1.1 Spring测试环境搭建 Spring模块概览,绿色是模块,Spring中八大模块,黑色表示该模块包含的jar包(组件).例如我们想要用IOC容器,也就是绿色的Co ...
- Spring源码系列(十二)Spring创建Bean的过程(二)
1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...
- Spring创建Bean的3种方式
1. Spring创建Bean的三种方式 1. 调用构造器(因为常用就不讲) 2. 调用静态工厂方法 3. 调用实例工厂方法 2. 使用静态工厂方法 1.此时<bean.../>元素要指定 ...
- Spring创建Bean的基本步骤
最简单的spring创建Bean主要分为以下几个步骤: 加载Class类 调用构造方法 设置属性 回调Aware(BeanNameAware, BeanFactoryAware) 回调初始化方法(In ...
- Spring5——(一)spingIOC(入门介绍,spring创建bean,依赖,注入,注解方式)
为什么要有框架? (1)对于web层来说,一个大型的程序往往需要编写大量的servlet,并且取值封装会非常繁琐. (2)对于dao层,要编写大量的sql语句,对于结果的解析也很麻烦,并且sql的复用 ...
- spring创建bean模式singleton与prototype的区别
spring 创建bean有单例模式(singleton)和原始模型模式(prototype)这两种模式. 在默认的情况下,Spring中创建的bean都是单例模式的(注意Spring的单例模式与Go ...
- Spring创建Bean的三种方式的使用和区别
在学习Spring的时候,发现Spring的IOC(控制反转)为我们提供的三种创建Bean的方式. 1.Spring创建Bean的三种方式 这里采用XML配置,分别演示三种创建Bean的方式和代码. ...
- Spring 创建Bean的三种方式
创建Bean的三种方式 第一种方式:使用默认构造函数创建. 在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时.采用的就是默认构造函数创建bean对象,此 ...
- Spring创建Bean的流程
大致步骤 简单来说:Bean会经历四个阶段: 实例化–>属性赋值–>初始化–>销毁 具体来说: 实例化:new xxx():有两个时候会触发实例化: 像容器申请一个Bean的时候 当 ...
最新文章
- 有关于Matlab的regionprops函数的PixelIdxList和PixelList的一点解释
- 斜率小于0的连线数量 51Nod - 1107 (树状数组+离散化)
- python好用-Python里三个好用的调试神器
- 开始学习Solaris
- desktop docker 无法卸载_docker,生信人的福音!
- bootstrap 打印组件_创想三维:有了3D打印机,后期该如何维护呢-创想三维 Ender-1_深圳3D打印机行情...
- php百度编辑器精简版,开源web编辑器|百度编辑器ueditor下载1.4.3.4php版 下载_久友软件下载...
- python模块补充
- 红外遥控c语言,NEC协议红外遥控器
- 《C程序员从校园到职场》一2.2 破除错误观念
- 手机照片×××作:千里走单骑
- Gym - 101142F Folding(折半)
- pcl_viewer 常用实用指令
- 备案网站建设方案书模板
- 智能小车-红外循迹篇
- 目标检测算法之CVPR 2019 Guided Anchoring
- mysql 文本挖掘_GitHub - HuiHuiT/dianping_textmining: 大众点评评论文本挖掘,包括点评数据爬取、数据清洗入库、数据分析、评论情感分析等的完整挖掘项目...
- 三星 android 4.4.4,我的手机是三星4.4.4安卓系统,怎么升级到6.1版本
- c语言已知加速度求位移速度,已知初速度,加速度,时间,求位移
- jqurey常用方法(jqurey设计思想)