一. Spring IOC容器概述
为什么使用 IOC, 而不使用工厂模式?
因为 IOC 是基于 Java 反射机制来实现的, 如果需要一旦改变, 工厂模式会进行相应的变化, 但是 IOC 的反射机制允许我们不重新编译代码,因为它的对象时动态生成的.
IOC 容器是将对象放入此容器中, 做到依赖注入和控制反转. 比如将对象Demo注入到容器中,容器代为管理,需要的时候,从容器中拿出来,拿的过程不需要自己去new, 还是注入时对象Demo. 这个主动权只是交给IOC, 也就是所说的控制反转.
对同一个对象的操作不同的解释.
控制反转是IOC容器的特色,我也会认为这是一种设计模式.
在Spring容器设计中可以看到有重要的两个容器系列: 一个是BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能;另一个是ApplicationContext应用上下文,它作为容器的高级形态而存在.它作为用户和IOC的桥梁.
如果把IOC比作是盛装水的水桶, BeanFactory就定义了可以作为水桶的基本功能,比如至少能装水,有提水等;BeanDefinition则作为水, ApplicationContext就是用来取水的工具.
1.Spring IOC容器的设计
主要接口设计图:
线路分析:
- 从接口BeanFactory到HierarchicalBeanFactory再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路径.这条路径定义了BeanFactory的IOC基本规范,包括了getBean()这样的基本方法.HierarchicalBeanFactory接口继承了BeanFactory增加了getParentBeanFactory()方法,使得BeanFactory具备了双亲IOC管理功能.
- 从BeanFactory到ListableBeanFactory再到ApplicationContext再到WebApplicationContext或者ConfigurableApplicationContext接口.我们常用的应用上下文WebApplicationContext和ConfigurableApplicationContext实现. ListableBeanFactory和HierarchicalBeanFactory 细化了BeanFactory接口功能,ApplicationContext继承MessageSource,ResourceLoader,ApplicationEventPublisher接口,对BeanFactory简单IOC接口基础上增加了许多高级容器特性的支持.
- 这里涉及主要的接口关系,而具体的IOC容器都在这个接口体系下实现的,比如:DefaultListableBeanFactory,这个类实现了ConfigurableBeanFactory, 从而成为一个简单IOC容器的实现.像其他IOC容器,比如:XmlBeanFactory,都是在DefaultListableBeanFactory的基础上做扩展, 同样ApplicationContext也是如此.
BeanFactory和FactoryBean区别:
在Spring中,所有的Bean都是由BeanFactory(IOC容器)来进行管理的;FactoryBean是Bean工厂.
2.IOC容器系列的设计与实现
BeanFactory接口方法
- getBean()方法,这个方法可以从IOC容器中获得管理的Bean.
- containsBean()让用户能够判断容器是否含有指定名字的Bean.
- getAliases()来查询指定了名字的Bean所有的别名,这些别名都是用户在BeanDefinition中定义的.
- isSingleton()来查询指定名字的Bean是否是Singleton类型的Bean,在BeanDefinition中定义.
- isTypeMatch()来查询指定了名字的Bean的Class类型是否是特定的Class类型.这个Class类型可以由用户来指定.
- isPrototype()来查询指定了名字的Bean是否是prototype类型.在BeanDefinition中定义.
- isTypeMatch()来查询指定了名字的Bean的Class类型是否是特定Class类型,这个Class类型可以由用户来指定.
- getType()来查询指定了名字的Bean的Class类型.
我们从XmlBeanFactory这个类来了解IOC容器设计原理.
XmlBeanFactory继承DefaultListableBeanFactory, 后者是整个bean加载和注册的核心.
- 创建IOC配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息.
- 创建一个BeanFactory,这里使用DefaultListableBeanFactory.
- 创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入xml文件形式的BeanDefinition,通过一个回调配置给BeanFactory.
- 从定义好的资源位置(定位)读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成. 再由其他类完成载入和注册.这个时候就建立好了IOC容器. 也就可以使用了.
XmlBeanDefinitionReader的loadBeanDefinitions()来对定位的配置信息读取.
再调用doLoadBeanDefinition方法.
此方法是用来解析指定xml生成DOM对象.
再调用registerBeanDefinitions方法,将解析xml统计解析的Bean数量或者说是需要载入的Bean数量.
这里documentReader.registerBeanDefinitions(doc, createReaderContext(resource));这个是解析过程入口,具体的解析由DefaultBeanDefinitionDocumentReader的registerBeanDefinitions来执行,具体执行过程看一下:
继续看doRegisterBeanDefinitions方法,如图:
继续看parseBeanDefinitions(root,this.delegate)方法,此方法是在文档的根级别解析元素,eg: 导入的,别名的,bean。 如图:
继续看parseDefaultElement(ele, delegate)方法,使用Spring的Bean规则解析元素节点, 如图:
方法中是根据对不同元素节点解析并注册到IOC容器中,我们看一下如果元素节点是bean元素,进行解析并注册,看注册代码。 如图:
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);该方法–解析Bean定义资源文件中的元素,这个方法中主要处理元素的id,name和别名属性,看如下代码
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
// 检测<bean>元素所配置的id或name唯一性,containingBean判断是否包含子<bean>元素
checkNameUniqueness(beanName, aliases, ele);
}
// 详细对<bean>元素中配置的bean进行解析的地方[property,description,parent等]
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
// 如果<bean>元素中没有配置id或name,且没有包含子<bean>元素,为解析的bean生成一个唯一的beanName并注册
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
解析完之后,返回BeanDefinitionHolder对象,并调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());此方法进行注册。
我们会在另一篇章讲解BeanDefinitionHolder和BeanDefinitionParserDelegate。
以上是对XmlBeanDefinitionReader类具体解析的xml的过程.
4.ApplicationContext容器的设计原理
在ApplicationContext容器中,我们以常用的FileSystemXmlApplicationContext的实现为例来说明ApplicationContext容器的设计原理.
在FileSystemXmlApplicationContext的设计中,其实在ApplicationContext主要功能已经在FileSystemXmlApplicationContext的基类AbstractXmlApplicationContext中实现了.
FileSystemXmlApplicationContext只需要实现与和它自身相关的两个功能设计.
一个功能是在实例化此的时候,同时启动IOC容器的refresh()过程.
public FileSystemXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
;
另一个是定位的需要解析的xml路径
protected Resource getResourceByPath(String path) {
if (path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
3. IOC容器的初始化过程
IOC初始化过程是由refresh()方法来启动的,这个方法标志着IOC容器的正式启动.这个过程包括BeanDefinition的定位,载入,注册.三个基本过程;
- 第一个过程是: Resource定位过程,这个Resource是定位BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供了统一接口. 就像水桶需要装水, 先找到水源.
- 第二个过程是将BeanDefinition载入,将用户定义好的Bean表示成IOC容器内部的数据结构.
- 第三个过程是向IOC容器注册这些BeanDefinition过程,这个过程是通过调用BeanDefinitionRegistry接口的实现类完成的. 注册的过程也就是将载入过程得到的BeanDefinition放入到IOC容器中.IOC容器是通过HashMap来持有这些BeanDefinition的.
注: 这个初始化过程,一般不包含Bean依赖注入的实现,在SpringIOC设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在第一次使用getBean向容器索取Bean的时候。但有一个列外那就是在使用IOC容器时有一个预实例化的配置(lazyinit),如果lazyinit true的时候,只有调用getBean时才对这个Bean载入和注册;如果lazyinit false , 在启动时就进行以上三个过程。
开始剖析以上三个过程:
3.1 BeanDefinition的Resource定位
ClassPathResource c = new ClassPathSource(“bean.xml”);
这里的Resource并不能由DefaultListableBanFactory直接使用,Spring通过BeanDefinitionReader来对这些信息进行处理。这里,可以看到ApplicationContext相对于直接使用DefaultListableBeanFactory的好处。因为在ApplicationContext中Spring为我们提供一系列加载不同Resource的读取器的实现。
getResourceByPath()方法是一个模板方法, 是为读取Resource服务的。不同的子类实现方式不同。
BeanDefinition的整个资源定位过程是在FileSystemXmlApplicationContext的构造函数中refresh()初始化触发的。
那么读取BeanDefinition的读入器是谁呢?此过程也是载入过程。 看如下图流程:
AbstractApplicationContext的方法refresh中执行的obtainFreshBeanFactory方法,如图:
obtainFreshBeanFactory方法执行到refreshBeanFactory方法(刷新工厂),此方法是抽象方法,具体实现交由子类实现,
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
其中子类AbstractRefreshableApplicationContext实现了方法,如图:
此方法执行到方法loadBeanDefinitions,loadBeanDefinitions方法在本类也是抽象方法
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);
其中子类AbstractXmlApplicationContext实现此loadBeanDefinitions方法,如图:
在这个方法中实例化XmlBeanDefinitionReader类,用来载入BeanDefinition。
具体的载入过程是由XmlBeanDefinitionReader的基类AbstractBeanDefinitionReader来完成的。
如图:
在此方法中进行载入(加载Bean)。
其中加载的过程是调用DefaultResourceLoader的getResource方法完成具体的Resource定位,
如图:
前面时候也说到FileSystemXmlApplicationContext对象的getResourceByPath的实现,返回的对象时FileSystemResource对象,此对象时Resource的子类,也是完成对BeanDefinition的定位。在完成对BeanDefinition定位的基础上,就可以通过返回的Resource对象来进行BeanDefinition的载入了,数据的读入将在下面的BeanDefinition的载入和解析中完成。 如果把IOC容器比喻为水桶,Resource就是水源,剩下就是怎么打水了。
3.2 BeanDefinition的载入和解析
在完成对BeanDefinition的Resource的定位分析之后,下面分析对BeanDefinition的载入和解析过程。对于IOC容器来说,载入过程就相当于把定义的BeanDefinition在IOC容器中转化成一个Spring内部表示的数据结构的过程,IOC容器对Bean管理和依赖注入功能的实现,是通过对持有的BeanDefinition进行各种相关操作来完成的。这些BeanDefinition是通过一个HashMap来保持和维护的。
先回到IOC容器初始化入口, refresh()方法。它详细描述了ApplicationContext的初始化过程,比如BeanFactory更新,MessageSource和PostProcessor的注册。这些过程为Bean生命周期提供了条件。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 调用容器准备刷新的方法, 获取容器的当前时间, 同时给容器设置同步的标识
prepareRefresh();
// 告诉子类启动refreshBeanFactory()的地方
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器
prepareBeanFactory(beanFactory);
try {
// 设置BeanFactory的后置处理
postProcessBeanFactory(beanFactory);
// 调用BeanFactory后处理器,这些后处理器是在Bean定义中向容器注册的
invokeBeanFactoryPostProcessors(beanFactory);
// 注册Bean的后处理器,在Bean创建过程中调用
registerBeanPostProcessors(beanFactory);
// 对上下文中的消息源进行初始化
initMessageSource();
// 初始化上下文中的事件机制
initApplicationEventMulticaster();
// 初始化其他特殊的Bean
onRefresh();
// 注册ApplicationListener为监听器
registerListeners();
// 实例化所有的non-lazy-init(,也就是在<bean id="testBeanFactoryPostProcessor"
// class="com.zhenqiang.interceptor.TestBeanFactoryPostProcessor"/>)没有加lazy-init
// 默认lazy-init = false
finishBeanFactoryInitialization(beanFactory);
// 发布容器事件,完成refresh过程
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 如果出现异常则销毁所有已生成的bean
destroyBeans();
// 如果出现异常, 取消上下文的刷新, active在抛出异常,重置标志
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...
// 在Spring的核心中重置常见的内省缓存,因为不再需要bean的元数据
resetCommonCaches();
}
}
}
- 其中ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();此方法是告诉子类来启动refreshBeanFactory()的地方,在这个方法中创建BeanFactory。在创建IOC容器前,如果已经有容器存在,那么先把已有的容器销毁和关闭。保证refresh以后使用的是新建立起来的IOC容器。如图:
方法中loadBeanDefinitions就是整个BeanDefinition载入的过程。这里展示的类是针对xml形式的。
然后解析成DOM对象,在上面XmlBeanDefinitionReader解析过程时提到过,这里不再做解释了。
那么obtainFreshBeanFactory()方法返回的对象ConfigurableListableBeanFactory就拿到统计所有要载入并注册了的bean。
3.3.3BeanDefinition在IOC容器中注册
将BeanDefinition进行注册,在DefaultListableBeanFactory中有一个HashMap来持有载入的BeanDefinition的,private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); 如下看注册流程:
调用接口BeanDefinitionRegister方法 registerBeanDefinition
调用实现类DefaultListableBeanFactory来实现此方法。
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
// 如果map中已有这个BeanDefinition,但又不允许覆盖,那么抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 如果不为空的化
if (hasBeanCreationStarted()) {
// synchronized是保证数据的一致性
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
完成了BeanDefinition注册,就完成了IOC容器的初始化过程。此时,在使用IOC容器DefaultListableBeanFactory中建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,它们都在beanDefinitionMap里被检索和使用。容器的作用就是对这些信息进行维护和处理。这些信息是依赖反转的基础。
4.IOC容器的依赖注入
为了进一步了解BeanDefinition依赖注入过程的实现,下面从DefaultListableBeanFactory的基类AbstractBeanFactory入手去看看getBean的实现,getBean是触发了依赖注入,
/**
* 这里是实际得到Bean的地方,也是触发依赖注入的地方
*/
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 先从缓存中中取得bean,处理那些已经被创建过的单件bean,对这种bean的请求不需要重复的创建。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 完成FactoryBean的相关处理,以取得FactoryBean的生产结果。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果我们创建了这个bean,则失败的原因是在一个循环引用中。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查BeanFactory是否存在这个bean,如果在当前工厂取不到,则到双亲BeanFactory中去取,如果在当前双亲BeanFactory取不到,那就顺着双亲BeanFactory链一直向上找。
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 {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 这里根据Bean的名字取得BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 获取当前Bean所有的依赖Bean,这样会触发getBean的递归调用,直到取到一个没有任何依赖Bean为止。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (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);
}
// 这里是创建property bean 的地方
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;
}
}
// 这里对创建的Bean进行类型检查,如果没有问题,就返回这个新创建的Bean,这个Bean已经是包含了依赖关系的Bean
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.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
这个就是依赖注入的入口,在这里触发了依赖注入,而依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的。
重点来说,getBean方法是依赖注入的起点,之后会调用createBean,下面通过createBean代码来了解这个实现过程。createBean不但生成了需要的bean,还对bean初始化进行了处理(防止循环引用),比如实现了BeanDefinition的init-method和Bean后置处理器。看AbstractAutowireCapableBeanFactory类方法doCreateBean看如下代码:
/**
* 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
* 真正创建bean的方法
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 封装被创建的bean对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) { // 如果是单列,先从缓存中同名的bean清除掉
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建实例对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
//获取实例化对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != org.springframework.beans.factory.support.NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// 调用PostProcessor后处理器
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.
// 向容器中缓存单态模式的bean对象,以防止循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 防止循环引用,尽早持有对象的引用.
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
// bean对象的初始化,依赖注入在此触发
Object exposedObject = bean;
try {
// 将bean实例对象封装,并且bean定义中配置的属性值赋值给实例对象
populateBean(beanName, mbd, instanceWrapper);
// 初始化实例对象
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) {
// 获取指定名称的已注册的单态bean对象
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 根据名称获取的已注册的bean和正在实例化的bean是同一个
if (exposedObject == bean) {
// 当前实例化的bean初始化完成
exposedObject = earlySingletonReference;
}
// 当前bean依赖其他bean时,并且发生循环依赖引用时,不允许新创建实例对象
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 获取当前bean所依赖的其他bean
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.
// 注册完成依赖注入的bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
在这里我们看到,与依赖注入关系特别密切的方法有createBeanInstance和populateBean,下面介绍这两个方法。
先分析createBeanInstance方法,看如下源码:
// 创建bean的实例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析Class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 确定class不为空,并且访问权限为public
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
// 异常为bean创建异常,bean class访问权限不为public并且不允许公开访问
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 配置一种callBack回调方法,通过这个回调方法创建bean
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 通过工厂方法创建
if (mbd.getFactoryMethodName() != null) {
// 调用工厂方法实例化
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 一个类可能有多个构造器,所以spring得根据参数个数、类型确定需要调用的构造器。
// 在使用构造器创建实例后,spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
// 已经解析过class的构造器
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 已经解析过class的构造器,使用已经解析好的构造器
if (autowireNecessary) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认无参构造实例化
return instantiateBean(beanName, mbd);
}
}
// 需要根据参数解析、确定构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 解析的构造器不为空 || 注入类型为构造函数自动注入 || bean定义中有构造函数 || 传入参数不为空
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 需要默认的无参构造实例化
return instantiateBean(beanName, mbd);
}
代码逻辑:
- 如果bean定义中存在InstanceSupplier,会使用这个回调接口创建对象。
- 根据配置的factoryMethodName或factory-method创建bean
- 解析构造函数并进行实例化
因为一个类可能有多个构造函数,所以需要根据配置文件中配置的参数或者传入的参数确定最终调用的构造函数。因为判断过程会比较消耗性能,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resovledConstructorOrFactoryMethod字段中。在下次创建相同bean的时候,会直接从RootBeanDefinition中的属性resovledConstructorOrFactoryMethod缓存的值获取,避免再次解析。 - createBeanInstance方法分析autowireConstructor方法,这个方法源码挺多的,如下源码:
// 有参构造方法实例化bean
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) {
// 实例化BeanWrapper,是包装bean的容器
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// 如果getBean中传入的参数不为空,那么就使用传入的参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
// 否则就解析配置文件中的参数
else {
Object[] argsToResolve = null;
// 先从缓存中获取
synchronized (mbd.constructorArgumentLock) {
// 缓存中的构造器
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// 从缓存中找到构造器,就继续从缓存中寻找缓存的构造器参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 没有缓存的参数,就需要获取配置文件的参数
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
// 如果缓存中没有缓存的参数的话,即argsToResolve不为空,就需要解析配置文件中的参数
if (argsToResolve != null) {
// 解析参数类型,比如将配置的string类型转成int、boolean等类型
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
// 如果没有缓存,就需要从构造函数开始解析
if (constructorToUse == null) {
// 是否需要解析器
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
if (explicitArgs != null) {
// getBean方法传入的参数
minNrOfArgs = explicitArgs.length;
}
else {
// 配置文件中的配置参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 用于承载解析后的构造函数参数的值
resolvedValues = new ConstructorArgumentValues();
// 解析配置文件中的参数,并且返回参数个数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 如果传入的构造器数组不为空,就使用传入的构造器参数,否则通过反射获取class中定义的构造器
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
// 使用public的构造器或者所有构造器
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
// 给构造函数排序,public构造函数优先,参数数量降序排序
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (constructorToUse != null && argsToUse.length > paramTypes.length) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
if (paramTypes.length < minNrOfArgs) {
continue;
}
// 封装解析到的参数信息
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
// 处理参数在配置文件中的情况
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
else {
// 处理参数由getBean方法传入的情况
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 因为不同构造函数的参数个数相同,而且参数类型为父子关系,所以需要找出类型最符合的一个构造函数
// spring用一个权重的形式来表示类型差异程度,差异权重越小越优先
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 当前构造函数最为匹配的话,清空先前ambiguousConstructors列表
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//存在相同权重的构造器,将构造器添加到一个ambiguousConstructors列表变量中
//注意,这时候constructorToUse 指向的仍是第一个匹配的构造函数
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//如果存在多个构造函数匹配程度相同,并且BeanDefinition中设置isLenientConstructorResolution为false(默认值为true),
//表示构造器创建为严格模式的话,抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//这一步就是将解析好的构造函数放入缓存resolvedConstructorOrFactoryMethod,如果需要的话也会缓存参数
//并设置constructorArgumentsResolved为true,表示已经解析过构造函数
if (explicitArgs == null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
try {
final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
Object beanInstance;
if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
beanFactory.getAccessControlContext());
}
else {
beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
bw.setBeanInstance(beanInstance);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
代码逻辑是:
- 确定参数
- 如果调用getBean方式时传入的参数不为空,则可以直接使用传入的参数;
- 再尝试从缓存中获取参数
- 否则,需要解析配置 节点时,配置的构造器参数。
- 确定构造函数
根据第一步中确定下来的参数,接下来的任务就是根据参数的个数、类型来确定最终调用的构造函数。首先是根据参数个数匹配,把所有构造函数根据参数个数升序排序,再去筛选参数个数匹配的构造函数;因为配置文件中可以通过参数位置索引,也可以通过参数名称来设定参数值,如// 使用初始化策略实例化对象 @Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. // 如果bean 定义中没有方法覆盖,则不需要cglib父类类的方法 // 直接使用反射来创建 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) { // 这是一个匿名内置类,通过反射获取bean的构造方法 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); } } } // 使用beanutils实例化,通过反射机制调用构造方法 new.instance(arg)来实例化, 前面有参构造已经介绍过 return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. // 使用cglib实例化, 前面有参构造已经分析了此源码 return instantiateWithMethodInjection(bd, beanName, owner); } }
到这里,我们已经分析了实例化Bean对象的整个过程,在实例化Bean对象生成的基础上,再介绍一下Spring是怎样对这些对象进行处理的,也就是Bean对象生成以后,怎样把这些Bean对象的依赖关系设置好,完成整个依赖过程。 这个过程涉及对各种Bean对象的属性的处理过程(即依赖关系处理的过程),这些依赖关系处理的依据就是已经解析得到的BeanDefinition。要详细了解这个过程,需要回到前面的populateBean方法。解析bean的属性值并注入。 现在看AbstractAutowireCapableBeanFactory类方法populateBean源码:
// 使用属性值填充给定BeanWrapper中的bean实例定义bean protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { // 如果有propertyValues,则抛出创建异常 if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { return; } } // 给任何实例化的后置处理器修改的机会 // 属性设置之前的bean状态,支持注入方式 boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 开始进行依赖注入过程,先处理autoWire的注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 对autoWire注入处理,根据bean的名字 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 对autoWire注入处理,根据bean的类型 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { if (pvs == null) { pvs = mbd.getPropertyValues(); } PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } if (pvs != null) { // 对属性进行注入 applyPropertyValues(beanName, mbd, bw, pvs); } }
这里我们说的是xml中定义的内容,我们平时用的@Resource @Autowired并不是在这里解析的,那些属于Spring注解的内容。
这里的autowire跟@Autowired不一样,autowire是Spring配置文件中的一个配置,@Autowired是一个注解。
继续走看对属性注入的代码:// 通过applyPropertyValues了解具体的对属性进行解析和注入的过程 protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { if (pvs.isEmpty()) { return; } if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } // 封装属性值 MutablePropertyValues mpvs = null; List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // 使用预先转换的值 try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } // 注意这个BeanDefinitionValueResolver对BeanDefinition的解析是在这个valueResolver中完成的 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // 这里为解析值创建一个副本,副本的数据将会被注入到bean中 List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { // 属性值已经转换 if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); // 将spring内部结构用来注入 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; // 属性值是否可以转换 boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { // 如果还可以转换,使用用户自定义的类型转换器转换属性值 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. // 存储转换后的属性值,避免每次属性注入时的转换工作 if (resolvedValue == originalValue) { if (convertible) { // 设置属性转换后的值 pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } // 属性是可转换的,且属性原始值是字符串类型,且属性原始值不是动态生成的字符串, else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // 这里是依赖注入发生的地方 try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
我们简单来看下这个代码的执行顺序:首先看属性是否已经是符合注入标准的类型MutablePropertyValues,如果是就直接开始注入–>否则,判断属性是否需要转换解析,需要的话则进行解析–>解析完成,开始注入。这里有一点要回忆一下,大家可记得我们在Beandefinition载入和解析的时候,对于Property元素及子元素做了一些操作,比如我们ref被解析成RuntimeBeanReference,list被解析成MangedList。那么,我们当时说了,这么做是为了把bean的配置解析成Spring能够认识的内部结构,所以这些内部结构现在就要被我们用来依赖注入了,Spring就是从这些结构中完成对属性的转换。继续看方法spring将内部结构用来依赖注入resolveValueIfNecessary代码:
// 将spring的内部结构用来依赖注入 @Nullable public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. // 对引用类型的属性进行解析 if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } // 对属性值是引用容器中另一个Bean名称的解析 else if (value instanceof RuntimeBeanNameReference) { String refName = ((RuntimeBeanNameReference) value).getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (!this.beanFactory.containsBean(refName)) { throw new BeanDefinitionStoreException( "Invalid bean name '" + refName + "' in bean reference for " + argName); } return refName; } // 对Bean属性的解析,主要是Bean中内部类 else if (value instanceof BeanDefinitionHolder) { // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases. BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value; return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition()); } else if (value instanceof BeanDefinition) { // Resolve plain BeanDefinition, without contained name: use dummy name. BeanDefinition bd = (BeanDefinition) value; String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(bd); return resolveInnerBean(argName, innerBeanName, bd); } // 对集合数组类型的属性解析 else if (value instanceof ManagedArray) { // May need to resolve contained runtime references. ManagedArray array = (ManagedArray) value; // 获取数组的类型 Class<?> elementType = array.resolvedElementType; if (elementType == null) { // 获取数组元素的类型 String elementTypeName = array.getElementTypeName(); if (StringUtils.hasText(elementTypeName)) { try { // 使用反射机制创建指定的类型 elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader()); array.resolvedElementType = elementType; } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, ex); } } else { // 没有获取数组的类型,也没有获取数组元素的类型,则直接设置数组的类型为Object elementType = Object.class; } } return resolveManagedArray(argName, (List<?>) value, elementType); } // 解析list集合 else if (value instanceof ManagedList) { // May need to resolve contained runtime references. return resolveManagedList(argName, (List<?>) value); } // 解析set集合 else if (value instanceof ManagedSet) { // May need to resolve contained runtime references. return resolveManagedSet(argName, (Set<?>) value); } // 解析map集合 else if (value instanceof ManagedMap) { // May need to resolve contained runtime references. return resolveManagedMap(argName, (Map<?, ?>) value); } // 解析properties else if (value instanceof ManagedProperties) { Properties original = (Properties) value; Properties copy = new Properties(); original.forEach((propKey, propValue) -> { if (propKey instanceof TypedStringValue) { propKey = evaluate((TypedStringValue) propKey); } if (propValue instanceof TypedStringValue) { propValue = evaluate((TypedStringValue) propValue); } if (propKey == null || propValue == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting Properties key/value pair for " + argName + ": resolved to null"); } copy.put(propKey, propValue); }); return copy; } // 解析String类型 else if (value instanceof TypedStringValue) { // Convert value to target type here. TypedStringValue typedStringValue = (TypedStringValue) value; Object valueObject = evaluate(typedStringValue); try { Class<?> resolvedTargetType = resolveTargetType(typedStringValue); if (resolvedTargetType != null) { return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType); } else { return valueObject; } } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, ex); } } else if (value instanceof NullBean) { return null; } else { return evaluate(value); } }
从上面的代码我们可以看到,这里的转换几乎完全跟BeanDefinitionParserDelegate中的parserPropertySubElement方法中对应,那里是为了将bean的配置解析成Spring内部结构,这里由于我们bean已经创建完成,所以我们需要将具体的属性值给赋值上真正的内容(比如引用类型,这时候就要真正的给一个bean实例)。
查看不同属性的解析,看代码:// 解决对工厂中另一个bean的引用 @Nullable private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { Object bean; // 获取引用的Bean名称 String refName = ref.getBeanName(); refName = String.valueOf(doEvaluate(refName)); // 如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象 if (ref.isToParent()) { if (this.beanFactory.getParentBeanFactory() == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available"); } bean = this.beanFactory.getParentBeanFactory().getBean(refName); } // 从当前的容器中获取指定的引用Bean对象,如果指定Bean对象没有被实例化则会递归触发引用Bean的初始化和依赖注入 else { bean = this.beanFactory.getBean(refName); // 将当前实例化对象的依赖引用对象 this.beanFactory.registerDependentBean(refName, this.beanName); } if (bean instanceof org.springframework.beans.factory.support.NullBean) { bean = null; } return bean; } catch (BeansException ex) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex); } } /** * For each element in the managed array, resolve reference if necessary. */ // 解析数组类型的属性 private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) { // 创建一个指定类型的数组,用于存放和返回解析后的数组 Object resolved = Array.newInstance(elementType, ml.size()); for (int i = 0; i < ml.size(); i++) { // 递归解析数组的每一个元素,并将解析后的值设置到resolved数组中,索引为i Array.set(resolved, i, resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i))); } return resolved; } /** * For each element in the managed list, resolve reference if necessary. */ // 解析list集合,同解析数组一个原理 private List<?> resolveManagedList(Object argName, List<?> ml) { List<Object> resolved = new ArrayList<>(ml.size()); for (int i = 0; i < ml.size(); i++) { resolved.add( resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i))); } return resolved; } /** * For each element in the managed set, resolve reference if necessary. */ // 解析set集合,同解析数组一个原理 private Set<?> resolveManagedSet(Object argName, Set<?> ms) { Set<Object> resolved = new LinkedHashSet<>(ms.size()); int i = 0; for (Object m : ms) { resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m)); i++; } return resolved; } /** * For each element in the managed map, resolve reference if necessary. */ // 解析Map集合,同解析数组一个原理 private Map<?, ?> resolveManagedMap(Object argName, Map<?, ?> mm) { Map<Object, Object> resolved = new LinkedHashMap<>(mm.size()); mm.forEach((key, value) -> { Object resolvedKey = resolveValueIfNecessary(argName, key); Object resolvedValue = resolveValueIfNecessary(new KeyedArgName(argName, key), value); resolved.put(resolvedKey, resolvedValue); }); return resolved; }
上面的代码我们可以从以下几个点来理解:
引用类型的解析:如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象 ,从当前容器取,如果对象没有创建,则递归调用getBean。
其他类型的解析:如list,递归解析list的每一个元素,又走了一遍resolveValueIfNecessary方法,也就是说如果list里面也是配置的ref,那么会递归调用到对引用类型解析。注意这里的递归调用。下面进入bean的依赖注入
通过上面的源码分析,我们已经得到了解析好的属性值,也就是说这时候的属性里面就是具体的对象,String等内容了。所以这时候我们就可以对属性进行注入了。在applyPropertyValues方法中,我们可以看到bw.setPropertyValues方法,我们看到的是AbstractPropertyAccessor.setPropertyValues,但是当我们点进去确实来到了AbstractPropertyAccessor类的方法中,我们先来跟一下这个方法setPropertyValues。// 该方法--调用入口 @Override public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException { List<PropertyAccessException> propertyAccessExceptions = null; // 得到属性列表 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues())); for (PropertyValue pv : propertyValues) { try { // This method may throw any BeansException, which won't be caught // here, if there is a critical failure such as no matching field. // We can attempt to deal only with less serious exceptions. // 属性注入 setPropertyValue(pv); } catch (NotWritablePropertyException ex) { if (!ignoreUnknown) { throw ex; } // Otherwise, just ignore it and continue... } catch (NullValueInNestedPathException ex) { if (!ignoreInvalid) { throw ex; } // Otherwise, just ignore it and continue... } catch (PropertyAccessException ex) { if (propertyAccessExceptions == null) { propertyAccessExceptions = new LinkedList<>(); } propertyAccessExceptions.add(ex); } } // If we encountered individual exceptions, throw the composite exception. if (propertyAccessExceptions != null) { PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]); throw new PropertyBatchUpdateException(paeArray); } }
上面代码的作用就是得到属性列表,并对每一个属性进行注入,setPropertyValue的具体实现是在AbstractNestablePropertyAccessor类中实现的,代码实现:
@Override public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException { AbstractNestablePropertyAccessor nestedPa; try { // 通过递归调用得到一个AbstractNestablePropertyAccessor实例 nestedPa = getPropertyAccessorForPropertyPath(propertyName); } catch (NotReadablePropertyException ex) { throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex); } PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName)); nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value)); }
查看getPropertyAccessorForPropertyPath方法代码:
// 通过递归调用得到一个AbstractNestablePropertyAccessor实例 protected AbstractNestablePropertyAccessor getPropertyAccessorForPropertyPath(String propertyPath) { int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath); // Handle nested properties recursively. if (pos > -1) { String nestedProperty = propertyPath.substring(0, pos); String nestedPath = propertyPath.substring(pos + 1); AbstractNestablePropertyAccessor nestedPa = getNestedPropertyAccessor(nestedProperty); return nestedPa.getPropertyAccessorForPropertyPath(nestedPath); } else { return this; } }
再查看getNestedPropertyAccessor方法代码:
// 为给定嵌套属性检索属性访问器。 //如果在缓存中没有找到,则创建一个新的。 private AbstractNestablePropertyAccessor getNestedPropertyAccessor(String nestedProperty) { if (this.nestedPropertyAccessors == null) { this.nestedPropertyAccessors = new HashMap<>(); } // Get value of bean property. // 获取bean的token PropertyTokenHolder tokens = getPropertyNameTokens(nestedProperty); String canonicalName = tokens.canonicalName; Object value = getPropertyValue(tokens); if (value == null || (value instanceof Optional && !((Optional) value).isPresent())) { if (isAutoGrowNestedPaths()) { value = setDefaultValue(tokens); } else { throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + canonicalName); } } // Lookup cached sub-PropertyAccessor, create new one if not found. AbstractNestablePropertyAccessor nestedPa = this.nestedPropertyAccessors.get(canonicalName); if (nestedPa == null || nestedPa.getWrappedInstance() != ObjectUtils.unwrapOptional(value)) { if (logger.isTraceEnabled()) { logger.trace("Creating new nested " + getClass().getSimpleName() + " for property '" + canonicalName + "'"); } nestedPa = newNestedPropertyAccessor(value, this.nestedPath + canonicalName + NESTED_PROPERTY_SEPARATOR); // Inherit all type-specific PropertyEditors. copyDefaultEditorsTo(nestedPa); copyCustomEditorsTo(nestedPa, canonicalName); this.nestedPropertyAccessors.put(canonicalName, nestedPa); } else { if (logger.isTraceEnabled()) { logger.trace("Using cached nested property accessor for property '" + canonicalName + "'"); } } return nestedPa; }
方法过程中调用getPropertyNameTokens方法或的token
// 解析指定的属性名称,并赋值到对应的属性标示中(PropertyTokenHolder) // String propertyName = "a[a["; ,tokens.keys=[a] private PropertyTokenHolder getPropertyNameTokens(String propertyName) { String actualName = null; List<String> keys = new ArrayList<>(2); int searchIndex = 0; while (searchIndex != -1) { int keyStart = propertyName.indexOf(PROPERTY_KEY_PREFIX, searchIndex); searchIndex = -1; if (keyStart != -1) { int keyEnd = propertyName.indexOf(PROPERTY_KEY_SUFFIX, keyStart + PROPERTY_KEY_PREFIX.length()); if (keyEnd != -1) { if (actualName == null) { actualName = propertyName.substring(0, keyStart); } String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd); if (key.length() > 1 && (key.startsWith("'") && key.endsWith("'")) || (key.startsWith("\"") && key.endsWith("\""))) { key = key.substring(1, key.length() - 1); } keys.add(key); searchIndex = keyEnd + PROPERTY_KEY_SUFFIX.length(); } } } PropertyTokenHolder tokens = new PropertyTokenHolder(actualName != null ? actualName : propertyName); if (!keys.isEmpty()) { tokens.canonicalName += PROPERTY_KEY_PREFIX + StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) + PROPERTY_KEY_SUFFIX; tokens.keys = StringUtils.toStringArray(keys); } return tokens; }
这里已经走完getPropertyAccessorForPropertyPath方法相关的流程。
现在继续走setPropertyValue方法,
真正的属性解析还在setPropertyValue方法中protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException { if (tokens.keys != null) { // token不为空的情况下 processKeyedProperty(tokens, pv); } else { // token为空的情况下 processLocalProperty(tokens, pv); } } @SuppressWarnings("unchecked") private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) { Object propValue = getPropertyHoldingValue(tokens); PropertyHandler ph = getLocalPropertyHandler(tokens.actualName); if (ph == null) { throw new InvalidPropertyException( getRootClass(), this.nestedPath + tokens.actualName, "No property handler found"); } Assert.state(tokens.keys != null, "No token keys"); String lastKey = tokens.keys[tokens.keys.length - 1]; if (propValue.getClass().isArray()) { Class<?> requiredType = propValue.getClass().getComponentType(); int arrayIndex = Integer.parseInt(lastKey); Object oldValue = null; try { if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) { oldValue = Array.get(propValue, arrayIndex); } Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(), requiredType, ph.nested(tokens.keys.length)); int length = Array.getLength(propValue); if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) { Class<?> componentType = propValue.getClass().getComponentType(); Object newArray = Array.newInstance(componentType, arrayIndex + 1); System.arraycopy(propValue, 0, newArray, 0, length); setPropertyValue(tokens.actualName, newArray); propValue = getPropertyValue(tokens.actualName); } Array.set(propValue, arrayIndex, convertedValue); } catch (IndexOutOfBoundsException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName, "Invalid array index in property path '" + tokens.canonicalName + "'", ex); } } else if (propValue instanceof List) { Class<?> requiredType = ph.getCollectionType(tokens.keys.length); List<Object> list = (List<Object>) propValue; int index = Integer.parseInt(lastKey); Object oldValue = null; if (isExtractOldValueForEditor() && index < list.size()) { oldValue = list.get(index); } Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(), requiredType, ph.nested(tokens.keys.length)); int size = list.size(); if (index >= size && index < this.autoGrowCollectionLimit) { for (int i = size; i < index; i++) { try { list.add(null); } catch (NullPointerException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName, "Cannot set element with index " + index + " in List of size " + size + ", accessed using property path '" + tokens.canonicalName + "': List does not support filling up gaps with null elements"); } } list.add(convertedValue); } else { try { list.set(index, convertedValue); } catch (IndexOutOfBoundsException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName, "Invalid list index in property path '" + tokens.canonicalName + "'", ex); } } } else if (propValue instanceof Map) { Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length); Class<?> mapValueType = ph.getMapValueType(tokens.keys.length); Map<Object, Object> map = (Map<Object, Object>) propValue; // IMPORTANT: Do not pass full property name in here - property editors // must not kick in for map keys but rather only for map values. TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType); Object convertedMapKey = convertIfNecessary(null, null, lastKey, mapKeyType, typeDescriptor); Object oldValue = null; if (isExtractOldValueForEditor()) { oldValue = map.get(convertedMapKey); } // Pass full property name and old value in here, since we want full // conversion ability for map values. Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(), mapValueType, ph.nested(tokens.keys.length)); map.put(convertedMapKey, convertedMapValue); } else { throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName, "Property referenced in indexed property path '" + tokens.canonicalName + "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]"); } } private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) { PropertyHandler ph = getLocalPropertyHandler(tokens.actualName); if (ph == null || !ph.isWritable()) { if (pv.isOptional()) { if (logger.isDebugEnabled()) { logger.debug("Ignoring optional value for property '" + tokens.actualName + "' - property not found on bean class [" + getRootClass().getName() + "]"); } return; } else { throw createNotWritablePropertyException(tokens.canonicalName); } } Object oldValue = null; try { Object originalValue = pv.getValue(); Object valueToApply = originalValue; if (!Boolean.FALSE.equals(pv.conversionNecessary)) { if (pv.isConverted()) { valueToApply = pv.getConvertedValue(); } else { if (isExtractOldValueForEditor() && ph.isReadable()) { try { oldValue = ph.getValue(); } catch (Exception ex) { if (ex instanceof PrivilegedActionException) { ex = ((PrivilegedActionException) ex).getException(); } if (logger.isDebugEnabled()) { logger.debug("Could not read previous value of property '" + this.nestedPath + tokens.canonicalName + "'", ex); } } } valueToApply = convertForProperty( tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor()); } pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue); } ph.setValue(valueToApply); } catch (TypeMismatchException ex) { throw ex; } catch (InvocationTargetException ex) { PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent( getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue()); if (ex.getTargetException() instanceof ClassCastException) { throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException()); } else { Throwable cause = ex.getTargetException(); if (cause instanceof UndeclaredThrowableException) { // May happen e.g. with Groovy-generated methods cause = cause.getCause(); } throw new MethodInvocationException(propertyChangeEvent, cause); } } catch (Exception ex) { PropertyChangeEvent pce = new PropertyChangeEvent( getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue()); throw new MethodInvocationException(pce, ex); } }
方法解析为:
- 根据tokens是否为空分为:集合类型和非集合类型。
- 集合类型的注入:一般都是这么个规律:根据key先去getter旧值,再取得已经转换好的真正的实例值,setter到指定的位置。也就是书上说的:将其属性值解析为目标类型的集合后直接赋值给属性
- 非集合类型:大量使用了JDK的反射和内省机制,通过属性的getter方法(reader method)获取指定属性注入以前的值,同时调用属性的setter方法(writer method)为属性设置注入后的值。
在此需要讲一下循环依赖的问题。