本文首发于个人公众号 Java 技术大杂烩,欢迎关注
相关文章
在文章 Spring 中 bean 注册的源码解析 和 Spring bean 创建过程源码解析 了解了 bean 的注册和创建过程,当通过 getBean
方法来获取对应 bean 的时候,会是如何的呢?
下面就来看看 getBean
方法的内部实现。在进入 getBean
方法内部之前,先来看看 FactoryBean
这个接口,因为在 getBean
方法内部会对该接口的实现类进行另外的处理。
这个接口和 BeanFactory
接口非常的像,但是作用却截然不同,先来看看 javadoc
文档的定义,大致意思就是:如果某个 bean 实现了这个接口,通过 getBean 方法来获取 bean 的时候,并不是返回自己的实例,而是返回其 getObject() 方法的返回值;此外 FactoryBeans 可以支持 singletons 和 prototypes 模式。它的源码如下,只有 三个 方法:
public interface FactoryBean<T> {
// 返回 bean 的实例,即调用 getBean 方法获取到的实例就是该方法的返回值
T getObject() throws Exception;
// 返回 bean 的类型
Class<?> getObjectType();
// 该 bean 是否是单例模式
boolean isSingleton();
}
那么这个 FactoryBean
接口有什么用呢?通过 Spring bean 创建过程源码解析 知道,bean
的实例化就是使用反射
和CGLIB
来实现的,但是在某些情况下,实例化 bean
过程比较复杂,如果按照传统的方式,则需要在配置文件 <bean>
中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。所以,用户可以通过实现该接口定制实例化bean
的逻辑。
先来看一个栗子,现在有个 User
对象,传统的方式,在配置文件中配置如下:
public class User {
private String name;
private int age;
private int sex;
private double money;
private String job;
// setter / getter / toString
}
<bean id="user" class="main.tsmyk.pojo.User">
<property name="name" value="zhangsan"/>
<property name="age" value="20"/>
<property name="job" value="java"/>
<property name="money" value="10000"/>
<property name="sex" value="1"/>
</bean>
测试:
ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
User user = (User) context.getBean("user");
System.out.println(user);
结果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}
从打印的结果可以看到 User 对象的属性都被附上了值
但是,如果 User
对象的属性很多,不想写很多的 <property>
标签,则可以通过 FactoryBean
接口来实现,在该接口内部,按照一定的规则来解析 User
对象的属性并赋值。如下所示:
public class UserFactoryBean implements FactoryBean<User> {
private String user;
@Override
public User getObject() throws Exception {
User user = new User();
String[] userInfos = this.user.split(";");
user.setName(userInfos[0]);
user.setAge(Integer.parseInt(userInfos[1]));
user.setJob(userInfos[2]);
user.setMoney(Double.parseDouble(userInfos[3]));
user.setSex(Integer.parseInt(userInfos[4]));
return user;
}
@Override
public Class<User> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return false;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
在该类的 getObject
方法内部对 User
对象的属性进行解析并赋值,通过 getBean
方法获取 bean
的时候,得到的就是 getObject
方法返回的 User
对象,配置如下:
<bean id="userFactory" class="main.tsmyk.beans.UserFactoryBean">
<property name="user" value="zhangsan;20;java;10000;1"/>
</bean>
测试:
ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
User user1 = (User) context.getBean("userFactory");
System.out.println(user1);
结果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}
可以看到和上面传统的方式是一样的。也验证了 getBean
方法获取到的是 getObject
方法的返回值,而不是 FactoryBean
实例本身;但是,如果就想获取到 FactoryBean
的实例本身,也是可以的,在 bean
的名字前加 &
符号就可以了,即 getBean("&userFactory")
测试:
ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
UserFactoryBean userBean = (UserFactoryBean) context.getBean("&userFactory");
System.out.println(userBean.getUser());
结果:zhangsan;20;java;10000;1
敲黑板:所以说,通过 getBean(String beanName)
方法来获取实例的时候,beanName
有可能是以 &
开头的,如果 beanName
以 &
开头,就表示处理的是 FactoryBean
接口
Spring
自身也提供了 FactoryBean
接口的很多实现,如 JndiObjectFactoryBean
类:
public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryBean<Object>, BeanFactoryAware, BeanClassLoaderAware {
private Object jndiObject;
// 其他复杂的计算,为 jndiObject 赋值
@Override
public Object getObject() {
return this.jndiObject;
}
}
我们熟知的第三方 ORM 框架 Mybatis
也提供了该接口的实现 SqlSessionFactoryBean
:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
// 其他配置
</bean>
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private SqlSessionFactory sqlSessionFactory;
@Override
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
}
return this.sqlSessionFactory;
}
// 其他方法
}
所以通过 getBean
方法获取的时候,得到的是 SqlSessionFactory
而不是 SqlSessionFactoryBean
现在来看看和 FactoryBean
很相似的一个接口 BeanFactory
,BeanFactory
它是 Spring IOC
容器的核心接口,它定义了容器的主要功能,如创建 bean,获取 bean 等,它是用来管理 bean 的,即它是用来实例化、定位、配置应用程序中的对象及建立这些对象间的依赖关系的。它的源码如下:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch);
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
可以看到定义了容器的基本功能,注意它有一个属性 FACTORY_BEAN_PREFIX = "&"
就是用来表示 FactoryBean
接口的 beanName
的前缀。
到这里,通过源码就可以看到,虽然 FactoryBean
和 BeanFactory
很像,但它们的作用完全不同,
FactoryBean
可以看做一个工厂,用它来创建一些复杂的 bean
BeanFactory
定义了 Spring 容器基本的功能,交由子类去实现,用于管理 bean
User user = (User) beanFactory.getBean("user");
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
接下来看下 doGetBean
方法,该方法有点复杂:
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly){
// 提取对应的 beanName,处理别名和FactoryBean接口的实现类,即 beanName 以 & 开头
final String beanName = transformedBeanName(name);
Object bean;
// 尝试从缓存中或者ObjectFactory中获取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("......");
}
// 这里主要处理 FactoryBean,有时候并不是返回实例本身,而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 缓存中不存在该bean的实例
else {
// 这里bean的作用域是原型模式,且存在循环依赖,出现循环依赖,则抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果当前的的beanDefinitionMap即配置文件不包含该bean,则从parentBeanFactory 中查找
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
// 这个 args 是 getBean(beanName, args...) 方法传入的
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// 如果不仅仅是做类型检查,则是创建bean,则进行标记,标记该bean以创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
// 将配置文件中GenericBeanDefinition转换为RootBeanDefinition,如果beanName是子bean的话,会合并父类的属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 处理依赖,如果存在依赖,则递归实例化依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException("........");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
//实例化 bean
if (mbd.isSingleton()) {
// 实例化单例的bean
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return createBean(beanName, mbd, args);
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 实例化原型的bean
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 指定的 score 上实例化bean
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
}
}
}
// 处理参数类型的转换
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
return (T) bean;
}
从 上述的代码可以看到,doGetBean
方法流程是很清晰的,每一步都使用对应的方法进行处理,它的流程主要如下:
beanName
,为什么要处理 beanName
呢,因为 bean 是可以有别名的,且,在上面介绍 FactoryBean
接口的时候,获取该 bean 的时,需要加上 &
前缀,所以这里要去掉&
singletonFactories
中加载,这个 singletonFactories
是什么呢? 在 Spring bean 创建过程源码解析 知道, bean 在创建的时候可能会存在依赖注入的情况,而在创建依赖 bean 的时候,为了 避免循环依赖,那么在创建该 bean 的时候,不等到 bean 创建完成就会把创建该 bean 的 ObjectFactory
放到 singletonFactories
缓存中,一旦下一个 bean 创建的时候,需要依赖上一个 bean 则直接从 singletonFactories
缓存中获取该 ObjectFactory
来进行创建,
比如 A 依赖 B,A --> B,现在创建 A 的实例 beanA,创建过程中,就把创建 A 的ObjectFactory
放到 singletonFactories
缓存中,现在发现 A 依赖于 B,则现在要去创建 B 的实例 beanB,当创建完 beanB 后才会继续创建 beanA;
如果现在发现 B 也依赖于 A,B --> A,那么在创建 beanB 的时候,也会先去创建 beanA,因为之前创建 A 的实例 beanA 的时候,已经把 A 的 ObjectFactory
放入到 缓存中了,现在直接去缓存中取出该 ObjectFactory
即可,试想一下,如果没有事先把 A 的 ObjectFactory
放到缓存中,那么在创建 B 的时候,先去创建 A ,创建 A 的时候发现依赖 B ,则又会去 创建 B,这样就会造成循环依赖,就会实例化失败。所以 Spring 是通过这种方法是解决 bean 之间循环依赖的,但是仅仅是处理单例的循环依赖,原型或其他的则会抛出异常
GenericBeanDefinition
转换为 RootBeanDefinition
,因为从配置文件加载 bean 的时候,是以 GenericBeanDefinition
方式保存的
3.3 处理依赖
3.4 创建 单例的 bean
3.5 创建 原型的 bean
3.6 创建其他 score 作用于的 bean
3.7 参数类型的转换流程是不是很清晰,再通过流程图来看更清晰:
下面看看每个部分。
当通过 getBean
方法获取 bean 的时候,bean 的 name 是可以以 &
开头的,即获取 FactoryBean
实例本身,此外,bean 还有别名,一个 bean 可以有多个别名等,所有在这里首先要提取 bean 的名称,即 方法 transformedBeanName
:
final String beanName = transformedBeanName(name);
protected String transformedBeanName(String name) {
String beanName = BeanFactoryUtils.transformedBeanName(name);
return canonicalName(beanName);
}
// 使用工具类 BeanFactoryUtils 来转名字
public static String transformedBeanName(String name) {
String beanName = name;
// 如果 beanName 以 & 开头,则去掉 &
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
// 返回去掉 & 后的 beanName
return beanName;
}
// 返回原始的bean的名字,解决别名
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
// while 循环,因为 bean 的别名可以有多个
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 处理 FactoryBean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 获取 bean
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从缓存中获取bean,该缓存singletonObjects用来存放已经创建完毕的bean的实例
Object singletonObject = this.singletonObjects.get(beanName);
// 如果缓存中没有,且该 bean 正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从正在创建bean的缓存中获取,该 earlySingletonObjects 缓存是用来存放正在创建且还没有创建完毕的bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果此时还是获取不到实例,且允许从ObjectFactory中获取,解决循环引用
if (singletonObject == null && allowEarlyReference) {
// 从 ObjectFactory 中获取对应的工厂,使用工厂创建创建对象,因为之前在创建该bean的时候且还没有创建完毕的时候,已经把该bean的 ObjectFactory 放入到缓存中
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 获取到工厂之后,进行创建bean的实例,并放入到对应的缓存中
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
// 如果缓存中没有,且该bean没有正在创建,则直接返回 nul
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
在该方法里面会尝试解决循环依赖,该方法会涉及到 3 个 map 类型的缓存:
singletonObjects
用来存放已经创建完毕的bean的实例earlySingletonObjects
是用来存放正在创建且还没有创建完毕的beanObjectFactory
用来存放对应的工厂,因为之前在创建该bean的时候且还没有创建完毕的时候,已经把该bean的 ObjectFactory
放入到缓存中所以上述方法的主要逻辑就是先从 singletonObjects
获取实例,如果获取不到,即该 bean 还没有创建;再从 earlySingletonObjects
获取,如果获取不到,即该bean没有正在创建,再从 ObjectFactory
获取对应的工厂来创建,如果到最后还是获取不到,则返回 null
获取到 bean的实例后,需要处理 诸如 FactoryBean
和 factory-method
之类的方法,在后面从不同的 score 获取到 bean 的实例后,都会执行该方法:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 如果 bean 的实例不是 FactoryBean 类型,即是一般的 bean ,可以直接返回
// 如果 beanName 是以 & 开头,则也直接返回,因为 beanName 以 & 开头,表示返回工厂实例本身
// BeanFactoryUtils.isFactoryDereference : name != null && name.startsWith("&")
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
// 尝试从 FactoryBean 缓存中获取bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 到这里,已经明确了 bean的实例一定是 FactoryBean 类型
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
// 通过 FactoryBean 来获取 bean 实例
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 忽略了其他代码
// doGetObjectFromFactoryBean -> factory.getObject(),返回的是 FactoryBean 的 getObject 方法的返回值
object = doGetObjectFromFactoryBean(factory, beanName);
return object;
}
经过了上述几步,发现从缓存中还不到实例的话,就会进行 bean 的实例化。当时在创建之前,如果该 bean 有依赖的 bean,则先会处理依赖的bean:
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException("循环依赖异常");
}
// 注册循环依赖
registerDependentBean(dep, beanName);
// 创建依赖的 bean
getBean(dep); // return doGetBean(name);
}
}
if (mbd.isSingleton()) {
// 创建单例的bean
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return createBean(beanName, mbd, args);
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 创建原型的bean
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 创建其他score的bean
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
单例的 bean和其他score的bean的创建可以参考 Spring bean 创建过程源码解析 的 createBean
方法。
下面来看看创建原型的bean的过程:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// 解析 class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 处理 lookup-method 和 replace-method 属性,在 “Spring 中 bean 注册的源码解析“ 从已经解析过
mbdToUse.prepareMethodOverrides();
// 在该方法里面会执行前置处理器和后置处理器
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果应用前置处理和后置处理器改变了bean,就直接返回,AOP功能就在此实现
if (bean != null) {
return bean;
}
// 正真创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
// 应用前置处理器和后置处理器
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 前置处理器
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
// 省略其他代码
return bean;
}
// 前置处理器
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
// 后置处理器
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
经过了上述的步骤之后,就会得到一个 bean 的实例,无论这个bean是单例的还是原型的,还是其他的score的,总之到这里就已经得到了 bean 的实例,得到实例之后,我们需要进行类型的转换,即 如果 bean 是一个 String,但是 requiredType 为 Integer ,则就需要进行类型的转换。
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
// 获取类型转换器
public TypeConverter getTypeConverter() {
TypeConverter customConverter = getCustomTypeConverter();
if (customConverter != null) {
return customConverter;
}
else {
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.setConversionService(getConversionService());
registerCustomEditors(typeConverter);
return typeConverter;
}
}
// 类型的转换
public <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field){
return doConvert(value, requiredType, null, field);
}
private <T> T doConvert(Object value, Class<T> requiredType, MethodParameter methodParam, Field field){
if (field != null) {
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
}
else {
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
}
}
// 正真类型的转换
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
// 自定义转换器
PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
ConversionFailedException conversionAttemptEx = null;
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
if (editor == null && conversionService != null && newValue != null && typeDescriptor != null)
{
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
}
}
}
// 省略其他代码
if (requiredType != null) {
if (convertedValue != null) {
// 类型为 class
if (Object.class == requiredType) {
return (T) convertedValue;
}
// 类型为数组
else if (requiredType.isArray()) {
if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
}
return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
}
// 类型为集合
else if (convertedValue instanceof Collection) {
convertedValue = convertToTypedCollection((Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
standardConversion = true;
}
// 类型为 map
else if (convertedValue instanceof Map) {
convertedValue = convertToTypedMap( (Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
standardConversion = true;
}
if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
convertedValue = Array.get(convertedValue, 0);
standardConversion = true;
}
// String
if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
return (T) convertedValue.toString();
}
// String
else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
Constructor<T> strCtor = requiredType.getConstructor(String.class);
return BeanUtils.instantiateClass(strCtor, convertedValue);
}
String trimmedValue = ((String) convertedValue).trim();
if (requiredType.isEnum() && "".equals(trimmedValue)) {
return null;
}
convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
standardConversion = true;
}
// number
else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
convertedValue = NumberUtils.convertNumberToTargetClass(
(Number) convertedValue, (Class<Number>) requiredType);
standardConversion = true;
}
}
else {
if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
convertedValue = javaUtilOptionalEmpty;
}
}
// 省略其他代码
return (T) convertedValue;
}
到这里 通过 getBean 就能获取到一个正确的 bean 了,
以上就是 getBean
方法的逻辑了,主要是需要知道 还可以通过 FactoryBean
来创建 bean,beanName 还可以是以 &
开头。