目录
spring创建bean的方式
-
构造方法
- 无参构造方法
- 有参构造方法
-
工厂方法
- 静态工厂方法
- 实例工厂方法
-
实现FactoryBean接口
前三篇《Spring源码分析系列——bean创建过程分析(一)——默认无参构造方法创建bean》、《Spring源码分析系列——bean创建过程分析(二)——有参构造方法创建bean》和《Spring源码分析系列——bean创建过程分析(三)——工厂方法创建bean》介绍了构造方法、工厂方法创建bean的主要流程,本篇分析一下实现FactoryBean接口方式创建bean
测试代码准备
xml配置如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean name="boyService2" class="yxf.instantiate.BoyFactoryBean">
</bean>
</beans>
实体类如下
public class Lad implements Boy {
private String name;
public Lad(String name) {
this.name = name;
}
@Override
public void play() {
System.out.println("I want to play game!");
}
}
public interface Boy {
void play();
}
实现FactoryBean接口类
//普通FactoryBean
public class BoyFactoryBean implements FactoryBean {
@Override
public Boy getObject() throws Exception {
return new Lad("niulang");
}
@Override
public Class<?> getObjectType() {
return Boy.class;
}
}
//实现SmartFactoryBean,并且重写isEagerInit()方法,返回true,会在容器加载就创建单例bean,急加载
public class BoyFactoryBean implements SmartFactoryBean {
@Override
public Boy getObject() throws Exception {
return new Lad("niulang");
}
@Override
public Class<?> getObjectType() {
return Boy.class;
}
@Override
public boolean isEagerInit() {
return true;
}
}
运行测试代码
public class MyXmlConfig {
public static void main(String[] args) throws Exception {
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
Lad lad = (Lad) ac.getBean("boyService2");
System.out.println(lad);
}
}
preInstantiateSingletons()方法分析
在经过AbstractApplicationContext的refresh()方法后,会调用DefaultListableBeanFactory的perInstantiateSingletons()方法,这个方法会在容器初始化后就实例化所有的单例bean。
看一下精简后的源码
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
//注册bean定义的名称集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 初始化所有非懒加载的单例bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果实现了FactoryBean接口,走这个创建bean
if (isFactoryBean(beanName)) {
//调用getBean方法,实例化实现了FactoryBean接口的类,FACTORY_BEAN_PREFIX = “&”
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
//如果具体实现的是SmartFactoryBean,且重写了isEagerInit()方法返回值true,则提前实例化bean
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
//非FactoryBean,普通getBean()创建bean
else {
getBean(beanName);
}
}
}
}
通过以上源码及注释,我们可以得到,在容器初始化后,就会实例化所有FactoryBean。并且如果具体实现的是SmartFactoryBean,且同时重写了isEagerInit()方法,返回值为true,则会实例化具体bean。
getBean(FACTORY_BEAN_PREFIX + beanName)创建FactoryBean分析
FACTORY_BEAN_PREFIX 是一个"&"符号
在doGetBean()方法会将它去掉
看一下部分源码
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
}
会通过transformedBeanName()方法将name转换为beanName,
再来看一下这个方法
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
再看BeanFactoryUtils.transformedBeanName(name)方法
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
//如果不是“&”开头,直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
//去掉"&"并返回真实的beanName
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
可以确定创建的factoryBean的beanName是实际bean的beanName。
再看下doGetBean()方法创建单例bean的代码
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
是通过getSingleton()方法。看一下代码
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//关键代码,这个就是执行的createBeab()方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
//将新创建的单例bean放入单例池
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
getSingleton()方法会将创建完的单例bean放入单例池,通过addSingleton()方法,来看一下代码
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//放入单例池,这里的beanName就是实际的beanName,没有带“&”
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
getBean(beanName)分析,创建实际bean
上一步已经将beanName及创建的factoryBean放入单例池了,所以会直接从单例池中取,不过如果直接取只能得到factoryBean,而不是实际bean。实际bean还没有创建,我们来看下怎么从factoryBean转换到真实bean。
看一下doGetBean()方法
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// 先从单例池中取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//将factoryBean转换为真实bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
}
因为之前已经在单例池中放入了key为beanName,value为factoryBean的新创建的工厂bean,此时就可以通过通过getSingleton(beanName)获取了,只不过获取的是factoryBean。
看一下getSingleton(beanName)方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例池singletonObjects中取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
重头戏是getObjectForBeanInstance()方法。这个方法把factoryBean转换为真实bean。这个方法经过一系列步骤最终会调用doGetObjectFromFactoryBean()方法。来看一下这个方法,
精简代码之后,如下
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
object = factory.getObject();
}
}
return object;
}
就是调用了factory的getObject()方法,然后将返回值返回去,而我们使用FactoryBean接口就是重写了getObject()方法,new出来我们真实的类,所以一切都明了啦!
总结
- 实现FactoryBean接口,重写getObject()方法,可以实现创建bean。稍微深入一点,如果具体实现SmartFactoryBean接口,并且同时重写了isEagerInit()方法,返回值设置为true,则可以在容器初始化时直接实例化单例bean,否则就是懒加载。
- 具体的实现过程是,在容器初始化的时候,先将factoryBean实例化,并且以真实的beanName为key放入单例池。调用的是getBean("&"+beanName)方法,获取的是factoryBean。
- 再调用getBean(beanName)方法,会从单例池中取到factoryBean,再将factoryBean转换为真实bean。具体是通过调用factoryBean的getObject()方法。这样就首尾呼应了。