一、@configuration

1.1 未加@configuration

<!--logback-test.xml,配置不打印日志-->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <logger name="org.springframework" level="off"/>
</configuration>

1.2 加上@configuration

1.3 cglib动态代理

二、源码跟踪

2.1 annotationconfigapplicationcontext

2.2 annotationconfigapplicationcontext#annotationconfigapplicationcontext(class<?>… annotatedclasses)

2.3 abstractapplicationcontext#refresh()

@override
	public void refresh() throws beansexception, illegalstateexception {
		// 同步,线程安全; 防止 fresh还没结束  就又进入改方法 导致容器初始化错乱
		synchronized (this.startupshutdownmonitor) {
			// 准备刷新 记录开始时间  设置几个标志位  验证环境属性
			preparerefresh();
 
			// 告诉子类刷新内部bean工厂  创建beanfactory  并且获取beandefinition的定义信息
			/**
			 *	obtainfreshbeanfactory();方法
			 *		解析为一个个beandefinition 放在我们beandefinitionmap中管理起来
			 *  1. refreshbeanfactory(); 核心方法
			 * 		abstractrefreshableapplicationcontext#refreshbeanfactory()
			 * 		创建defaultlistablebeanfactory 并设置属性
			 * 		加载beanfactory; 根据不同的类型,调用不同的方法
			 * 			org.springframework.context.support.abstractxmlapplicationcontext#loadbeandefinitions(org.springframework.beans.factory.support.defaultlistablebeanfactory)
			 */
			configurablelistablebeanfactory beanfactory = obtainfreshbeanfactory();
 
			// 准备在这种情况下使用的bean工厂  向beanfactory中设置一些属性  。对beanfactory 进行各种功能填充
			preparebeanfactory(beanfactory);
 
			try {
				// 允许在上下文 的子类中对bean工厂进行后处理  由子类去实现; 主要是自定义去使用
				postprocessbeanfactory(beanfactory);
 
				// 第5步 【beanfactorypostprocessors ;bean工厂后置处理器】调用我们的bean工厂后置处理器 (所有实现接口beanfactorypostprocessor接口的)
				//		主要是
				// 		会在此将class扫描成beandefinition 并注册bean 到一个beandefinitionmap中 这个过程使用到代理
				//beanfactorypostprocessor 可以 用于容器完成初始化()
				// 此处可以 还没有实例化bean之前读取bean的信息,并作出一些修改。
				// 例如修改bean的属性,修改bean的scope等
				invokebeanfactorypostprocessors(beanfactory);
 
				//https://blog.csdn.net/caihaijiang/article/details/35552859
				// 【beanpostprocessors ;bean后置处理器】 注册beanpostprocessor
				// beanpostprocessor是bean的后置处理器,
				// 在bean的初始化方法[initializingbean 以及init-method]前,后执行。
				registerbeanpostprocessors(beanfactory);
 
				// 为上下文初始化message 源, 即不同语言的消息体, 国际化处理 i18n
				initmessagesource();
 
				// 初始化事件传播器
				//初始化应用消息广播器, 并放入"applicationeventmulticaster" bean 中
				initapplicationeventmulticaster();
 
				// 扩展的一个实现 ,留给子类来初始化其它的bean。如springboot内嵌的tomcat在这个阶段完成
				onrefresh();
 
				// 注册监听器
				// 在所有注册的bean 中查找listener bean , 注册到消息广播报中
				registerlisteners();
 
				/**第11步
					对于非抽象类、非延迟初始化的单例bean,
					在spring容器启动的时候调用getbean方法来实例化bean, 并进行相关初始化工作,
					getbean方法最终调用abstractautowirecapablebeanfactory.docreatebean方法
				 */
				// 在创建beanfactory的过程中,beandefinition注册到了beanfactory中的一个concurrethashmap对象中
				// 以beanname为key,beandefinition为value ; 实例化所有剩余的(非延迟初始化)单例。
				finishbeanfactoryinitialization(beanfactory);
 
				// 第12步 最后一步:发布相应的事件。
				//完成刷新过程, 通知生命周期处现器lifecycleprocessor 刷新过程, 同时发出contextrefreshevent 通知别人
				finishrefresh();
			}
 
			catch (beansexception ex) {
				if (logger.iswarnenabled()) {
					logger.warn("exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
 
				// 第13步 销毁以创建的bean
				destroybeans();
 
				//取消refresh操作,重置容器的同步标识
				cancelrefresh(ex);
 
				// propagate exception to caller.
				throw ex;
			}
 
			finally {
				resetcommoncaches();
			}
		}
	}

2.4 abstractapplicationcontext#invokebeanfactorypostprocessors

2.5 postprocessorregistrationdelegate#invokebeanfactorypostprocessors

public static void invokebeanfactorypostprocessors(
			configurablelistablebeanfactory beanfactory, list<beanfactorypostprocessor> beanfactorypostprocessors) {
 
		set<string> processedbeans = new hashset<>();
 
		// 对beandefinitionregistry 类型的处理
		if (beanfactory instanceof beandefinitionregistry) {
			beandefinitionregistry registry = (beandefinitionregistry) beanfactory;
			list<beanfactorypostprocessor> regularpostprocessors = new arraylist<>();
			// 用于存放beandefinitionregistrypostprocessor
			list<beandefinitionregistrypostprocessor> registryprocessors = new arraylist<>();
 
			// 遍历所有的beanfactorypostprocessors,将beandefinitionregistrypostprocessor和普通beanfactorypostprocessor区分开
			for (beanfactorypostprocessor postprocessor : beanfactorypostprocessors) {
				if (postprocessor instanceof beandefinitionregistrypostprocessor) {
					beandefinitionregistrypostprocessor registryprocessor =
							(beandefinitionregistrypostprocessor) postprocessor;
					/**
						对于beandefinitionregistrypostprocessor 类型, 在beanfactorypostprocessor 的
						基础上还有自己定义的方法,需要先调用
					 */
					registryprocessor.postprocessbeandefinitionregistry(registry);
					registryprocessors.add(registryprocessor);
				}
				else {
					// 记录常规beanfactorypostprocessor
					regularpostprocessors.add(postprocessor);
				}
			}
 
			/**
				不要在这里初始化factorybeans: 我们需要保留所有常规bean未初始化,让bean工厂后处理器应用到它们!
				beandefinitionregistrypostprocessors之间的分离实现排好序,点好,等等。
				获取spring配置文件中定义的所有实现beanfactorypostprocessor接口的bean,然后根据优先级进行排序
			 */
			list<beandefinitionregistrypostprocessor> currentregistryprocessors = new arraylist<>();
 
			// 首先,调用实现优先排序的beandefinitionregistrypostprocessors
			string[] postprocessornames =
					beanfactory.getbeannamesfortype(beandefinitionregistrypostprocessor.class, true, false);
			for (string ppname : postprocessornames) {
				// priorityordered.class 优先排序
				if (beanfactory.istypematch(ppname, priorityordered.class)) {
					currentregistryprocessors.add(beanfactory.getbean(ppname, beandefinitionregistrypostprocessor.class));
					processedbeans.add(ppname);
				}
			}
			sortpostprocessors(currentregistryprocessors, beanfactory);
			registryprocessors.addall(currentregistryprocessors);
			invokebeandefinitionregistrypostprocessors(currentregistryprocessors, registry);
			currentregistryprocessors.clear();
 
			// 接下来,调用实现ordered的beandefinitionregistrypostprocessors
			postprocessornames = beanfactory.getbeannamesfortype(beandefinitionregistrypostprocessor.class, true, false);
			for (string ppname : postprocessornames) {
				// ordered.class
				if (!processedbeans.contains(ppname) && beanfactory.istypematch(ppname, ordered.class)) {
					currentregistryprocessors.add(beanfactory.getbean(ppname, beandefinitionregistrypostprocessor.class));
					processedbeans.add(ppname);
				}
			}
			sortpostprocessors(currentregistryprocessors, beanfactory);
			registryprocessors.addall(currentregistryprocessors);
			invokebeandefinitionregistrypostprocessors(currentregistryprocessors, registry);
			currentregistryprocessors.clear();
 
			// finally, invoke all other beandefinitionregistrypostprocessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postprocessornames = beanfactory.getbeannamesfortype(beandefinitionregistrypostprocessor.class, true, false);
				for (string ppname : postprocessornames) {
					if (!processedbeans.contains(ppname)) {
						currentregistryprocessors.add(beanfactory.getbean(ppname, beandefinitionregistrypostprocessor.class));
						processedbeans.add(ppname);
						reiterate = true;
					}
				}
				sortpostprocessors(currentregistryprocessors, beanfactory);
				registryprocessors.addall(currentregistryprocessors);
				invokebeandefinitionregistrypostprocessors(currentregistryprocessors, registry);
				currentregistryprocessors.clear();
			}
 
			// now, invoke the postprocessbeanfactory callback of all processors handled so far.
			// 调用configurationclasspostprocessor#postprocessbeanfactory增强配置类
			// 通过cglib生成增强类
			// 设置beandefinition的beanclass为增强类,让@bean生成的bean是单例
			invokebeanfactorypostprocessors(registryprocessors, beanfactory);
			invokebeanfactorypostprocessors(regularpostprocessors, beanfactory);
		}
 
		else {
			// invoke factory processors registered with the context instance.
			invokebeanfactorypostprocessors(beanfactorypostprocessors, beanfactory);
		}
 
		// beanfactorypostprocessor.class类型
		// do not initialize factorybeans here: we need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		string[] postprocessornames =
				beanfactory.getbeannamesfortype(beanfactorypostprocessor.class, true, false);
		// 筛选出bean工程中存在的所有实现beanfactorypostprocessor类的类名称
 
		// separate between beanfactorypostprocessors that implement priorityordered,
		// ordered, and the rest.
		list<beanfactorypostprocessor> priorityorderedpostprocessors = new arraylist<>();
		list<string> orderedpostprocessornames = new arraylist<>();
		list<string> nonorderedpostprocessornames = new arraylist<>();
		for (string ppname : postprocessornames) {
			if (processedbeans.contains(ppname)) {
				// skip - already processed in first phase above
				// 已经存在了,不再处理
			}
			else if (beanfactory.istypematch(ppname, priorityordered.class)) {
				// 为priorityordered类型
				priorityorderedpostprocessors.add(beanfactory.getbean(ppname, beanfactorypostprocessor.class));
			}
			else if (beanfactory.istypematch(ppname, ordered.class)) {
				// 为ordered类型
				orderedpostprocessornames.add(ppname);
			}
			else {
				// 这个就是我们当前需要关心的postprocessors
				//nonorderedpostprocessors添加的不是bean实例,而是beandefinition
				nonorderedpostprocessornames.add(ppname);
			}
		}
 
		// first, invoke the beanfactorypostprocessors that implement priorityordered.
		sortpostprocessors(priorityorderedpostprocessors, beanfactory);
		invokebeanfactorypostprocessors(priorityorderedpostprocessors, beanfactory);
 
		// next, invoke the beanfactorypostprocessors that implement ordered.
		list<beanfactorypostprocessor> orderedpostprocessors = new arraylist<>();
		for (string postprocessorname : orderedpostprocessornames) {
			orderedpostprocessors.add(beanfactory.getbean(postprocessorname, beanfactorypostprocessor.class));
		}
		sortpostprocessors(orderedpostprocessors, beanfactory);
		invokebeanfactorypostprocessors(orderedpostprocessors, beanfactory);
 
		// finally, invoke all other beanfactorypostprocessors.
		list<beanfactorypostprocessor> nonorderedpostprocessors = new arraylist<>();
		for (string postprocessorname : nonorderedpostprocessornames) {
			nonorderedpostprocessors.add(beanfactory.getbean(postprocessorname, beanfactorypostprocessor.class));
		}
		invokebeanfactorypostprocessors(nonorderedpostprocessors, beanfactory);
 
		// clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		beanfactory.clearmetadatacache();
	}

2.6 postprocessorregistrationdelegate#invokebeanfactorypostprocessors

2.7 configurationclasspostprocessor#postprocessbeanfactory

2.8 configurationclaasspostprocessor#enhanceconfigurationclasses

public void enhanceconfigurationclasses(configurablelistablebeanfactory beanfactory) {
		map<string, abstractbeandefinition> configbeandefs = new linkedhashmap<>();
		for (string beanname : beanfactory.getbeandefinitionnames()) {
			beandefinition beandef = beanfactory.getbeandefinition(beanname);
			// 判断是否是一个全注解类
			// 扫描是全注解类?full和lite的关系
			if (configurationclassutils.isfullconfigurationclass(beandef)) {
				if (!(beandef instanceof abstractbeandefinition)) {
					throw new beandefinitionstoreexception("cannot enhance @configuration bean definition '" +
							beanname + "' since it is not stored in an abstractbeandefinition subclass");
				}
				else if (logger.isinfoenabled() && beanfactory.containssingleton(beanname)) {
					logger.info("cannot enhance @configuration bean definition '" + beanname +
							"' since its singleton instance has been created too early. the typical cause " +
							"is a non-static @bean method with a beandefinitionregistrypostprocessor " +
							"return type: consider declaring such methods as 'static'.");
				}
				// 是全注解,需要代理,添加到configbeandefs中
				configbeandefs.put(beanname, (abstractbeandefinition) beandef);
			}
		}
		if (configbeandefs.isempty()) {
			// nothing to enhance -> return immediately
			return;
		}
 
		configurationclassenhancer enhancer = new configurationclassenhancer();
		// 遍历这个map
		for (map.entry<string, abstractbeandefinition> entry : configbeandefs.entryset()) {
			abstractbeandefinition beandef = entry.getvalue();
			// if a @configuration class gets proxied, always proxy the target class
			beandef.setattribute(autoproxyutils.preserve_target_class_attribute, boolean.true);
			try {
				// set enhanced subclass of the user-specified bean class
				class<?> configclass = beandef.resolvebeanclass(this.beanclassloader);
				if (configclass != null) {
					// 进行cglib代理,为@configuration注解的类生成增强类
					class<?> enhancedclass = enhancer.enhance(configclass, this.beanclassloader);
					if (configclass != enhancedclass) {
						if (logger.istraceenabled()) {
							logger.trace(string.format("replacing bean definition '%s' existing class '%s' with " +
									"enhanced class '%s'", entry.getkey(), configclass.getname(), enhancedclass.getname()));
						}
						// 再通过beandef.setbeanclass(enhancedclass)修改beandefinition的beanclass属性,
						// 在bean实例化阶段,会利用反射技术将beanclass属性对应的类实例化出来
						// 所以最终实例化出来的@configuration bean是一个代理类的实例
						beandef.setbeanclass(enhancedclass);
					}
				}
			}
			catch (throwable ex) {
				throw new illegalstateexception("cannot load configuration class: " + beandef.getbeanclassname(), ex);
			}
		}

2.9 configurationclassutils#checkconfigurationclasscandidate

1.在configurationclassutils类中的checkconfigurationclasscandidate标记是full @configuration还是lite @bean mode

2.通过”full”.equals(configclassattr)判断是否是全类注解是全注解

3.则将beandefinition放入map中configbeandefs.put

4.遍历这个map

5.使用cglib技术为配置类生成一个enhancedclass

6.通过enhancer.enhance进行cglib代理,为@configuration注解的类生成增强类

7.再通过beandef.setbeanclass(enhancedclass)修改beandefinition的beanclass属性,在bean实例化阶段,会利用反射技术将beanclass属性对应的类实例化出来,所以最终实例化出来的@configuration bean是一个代理类的实例

使用了@configuration注解的类,属于full @configuration。@configuration类允许通过调用同一类中的其他@bean方法来定义bean之间的依赖关系,保证@bean的对象作用域受到控制,避免多例。

@configuration类中的@bean地方会被cglib进行代理。spring会拦截该方法的执行,在默认单例情况下,容器中只有一个bean,所以我们多次调用user()方法,获取的都是同一个对象。

对于@configuration注解的类中@bean标记的方法,返回的都是一个bean,在增强的方法中,spring会先去容器中查看一下是否有这个bean的实例了,如果有了的话,就返回已有对象,没有的话就创建一个,然后放到容器中。

2.10 configurationclassenhancer#enhance

2.11 configurationclassenhancer#newenhancer

2.12 configurationclassenhancer#callbacks

2.13 configurationclassenhancer#intercept

2.13.1 configurationclassenhancer#iscurrentlyinvokedfactorymethod

2.14 configurationclassenhancer#resolvebeanreference

	private object resolvebeanreference(method beanmethod, object[] beanmethodargs,
				configurablebeanfactory beanfactory, string beanname) {
 
			// the user (i.e. not the factory) is requesting this bean through a call to
			// the bean method, direct or indirect. the bean may have already been marked
			// as 'in creation' in certain autowiring scenarios; if so, temporarily set
			// the in-creation status to false in order to avoid an exception.
			// 判断他是否正在创建
			boolean alreadyincreation = beanfactory.iscurrentlyincreation(beanname);
			try {
				if (alreadyincreation) {
					beanfactory.setcurrentlyincreation(beanname, false);
				}
				boolean useargs = !objectutils.isempty(beanmethodargs);
				if (useargs && beanfactory.issingleton(beanname)) {
					// stubbed null arguments just for reference purposes,
					// expecting them to be autowired for regular singleton references?
					// a safe assumption since @bean singleton arguments cannot be optional...
					for (object arg : beanmethodargs) {
						if (arg == null) {
							useargs = false;
							break;
						}
					}
				}
				object beaninstance = (useargs ? beanfactory.getbean(beanname, beanmethodargs) :
						beanfactory.getbean(beanname));
				if (!classutils.isassignablevalue(beanmethod.getreturntype(), beaninstance)) {
					// detect package-protected nullbean instance through equals(null) check
					if (beaninstance.equals(null)) {
						if (logger.isdebugenabled()) {
							logger.debug(string.format("@bean method %s.%s called as bean reference " +
									"for type [%s] returned null bean; resolving to null value.",
									beanmethod.getdeclaringclass().getsimplename(), beanmethod.getname(),
									beanmethod.getreturntype().getname()));
						}
						beaninstance = null;
					}
					else {
						string msg = string.format("@bean method %s.%s called as bean reference " +
								"for type [%s] but overridden by non-compatible bean instance of type [%s].",
								beanmethod.getdeclaringclass().getsimplename(), beanmethod.getname(),
								beanmethod.getreturntype().getname(), beaninstance.getclass().getname());
						try {
							beandefinition beandefinition = beanfactory.getmergedbeandefinition(beanname);
							msg += " overriding bean of same name declared in: " + beandefinition.getresourcedescription();
						}
						catch (nosuchbeandefinitionexception ex) {
							// ignore - simply no detailed message then.
						}
						throw new illegalstateexception(msg);
					}
				}
				method currentlyinvoked = simpleinstantiationstrategy.getcurrentlyinvokedfactorymethod();
				if (currentlyinvoked != null) {
					string outerbeanname = beanannotationhelper.determinebeannamefor(currentlyinvoked);
					beanfactory.registerdependentbean(beanname, outerbeanname);
				}
				return beaninstance;
			}
			finally {
				if (alreadyincreation) {
					beanfactory.setcurrentlyincreation(beanname, true);
				}
			}
		}

三、总结

  •  lite @bean mode :当@bean方法在没有使用@configuration注解的类中声明时称之为lite @bean mode
  • full @configuration:如果@bean方法在使用@configuration注解的类中声明时称之为full @configuration

full @configuration中的@bean方法会被cglib所代理,而 lite @bean mode中的@bean方法不会被cglib代理

@configuration注解作用

1.告诉spring这是一个配置类,相当于spring的xml配置文件

2.被@configuration 注解的类,会被cglib代理进行增强

3.@configuration类允许通过调用同一类中的其他@bean方法来定义bean之间的依赖关系,保证@bean的对象作用域受到控制,避免多例

@configuration注解底层是如何实现的,通过源码咱们可以反推并总结为以下几点:

1.spring首先会获取到所有的beandefenition

2.configurationclassutils类中checkconfigurationclasscandidate方法判断是full @configuration还是lite @bean mode

3.通过configurationclasspostprocessor后置处理器遍历所有的beandefenition

4.将标记了full @configuration模式的beandefenition,会对这个类进行cglib代理,生成一个代理类,并把这个类设置到beandefenition的class属性中

5.配置类会被cglib增强(生成代理对象),放进ioc容器内的是代理

6.对于内部类是没有限制的:可以是full模式或者lite模式

7.配置类内部可以通过方法调用来处理依赖,并且能够保证是同一个实例,都指向ioc内的那个单例

8.需要用这个bean实例的时候,从这个class属性中拿到的class对象进行反射,最终反射出来的是代理增强后的类

9.通过@configuration标注类的bean,spring会先去容器中查看是否有这个bean实例,如果有就返回已有的对象,没有就创建一个,然后放到容器中

到此这篇关于spring源码解析之configuration的文章就介绍到这了,更多相关configuration源码内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!