共计 8577 个字符,预计需要花费 22 分钟才能阅读完成。
这篇文章主要介绍了 Spring 这么初始化 Bean 实例对象的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇 Spring 这么初始化 Bean 实例对象文章都会有所收获,下面我们一起来看看吧。
代码入口
DefaultListableBeanFactory 的 preInstantiateSingletons 方法
DefaultListableBeanFactory 的 preInstantiateSingletons 方法,顾名思义,初始化所有的单例 Bean,看一下方法的定义:
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info(Pre-instantiating singletons in + this);
}
synchronized (this.beanDefinitionMap) {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List String beanNames = new ArrayList String (this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() bd.isSingleton() !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction Boolean () {
public Boolean run() {
return ((SmartFactoryBean) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean
((SmartFactoryBean) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
}
}
前面的代码比较简单,根据 beanName 拿到 BeanDefinition(即 Bean 的定义)。由于此方法实例化的是所有非懒加载的单例 Bean,因此要实例化 Bean,必须满足 11 行的三个定义:
(1)不是抽象的
(2)必须是单例的
(3)必须是非懒加载的
接着简单看一下第 12 行~ 第 29 行的代码,这段代码主要做的是一件事情:首先判断一下 Bean 是否 FactoryBean 的实现,接着判断 Bean 是否 SmartFactoryBean 的实现,假如 Bean 是 SmartFactoryBean 的实现并且 eagerInit(这个单词字面意思是渴望加载,找不到一个好的词语去翻译,意思就是定义了这个 Bean 需要立即加载的意思)的话,会立即实例化这个 Bean。Java 开发人员不需要关注这段代码,因为 SmartFactoryBean 基本不会用到,我翻译一下 Spring 官网对于 SmartFactoryBean 的定义描述:
FactoryBean 接口的扩展接口。接口实现并不表示是否总是返回单独的实例对象,比如 FactoryBean.isSingleton() 实现返回 false 的情况并不清晰地表示每次返回的都是单独的实例对象
不实现这个扩展接口的简单 FactoryBean 的实现,FactoryBean.isSingleton() 实现返回 false 总是简单地告诉我们每次返回的都是单独的实例对象,暴露出来的对象只能够通过命令访问
注意:这个接口是一个有特殊用途的接口,主要用于框架内部使用与 Spring 相关。通常,应用提供的 FactoryBean 接口实现应当只需要实现简单的 FactoryBean 接口即可,新方法应当加入到扩展接口中去
代码示例
为了后面的代码分析方便,事先我定义一个 Bean:
package org.xrq.action;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
public class MultiFunctionBean implements InitializingBean, BeanNameAware, BeanClassLoaderAware {
private int propertyA;
private int propertyB;
public int getPropertyA() {
return propertyA;
}
public void setPropertyA(int propertyA) {
this.propertyA = propertyA;
}
public int getPropertyB() {
return propertyB;
}
public void setPropertyB(int propertyB) {
this.propertyB = propertyB;
}
public void initMethod() {
System.out.println(Enter MultiFunctionBean.initMethod()
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println(Enter MultiFunctionBean.setBeanClassLoader(ClassLoader classLoader)
}
@Override
public void setBeanName(String name) {
System.out.println(Enter MultiFunctionBean.setBeanName(String name)
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(Enter MultiFunctionBean.afterPropertiesSet()
}
@Override
public String toString() {
return MultiFunctionBean [propertyA= + propertyA + , propertyB= + propertyB +]
}
}
定义对应的 spring.xml:
?xml version= 1.0 encoding= UTF-8 ?
beans xmlns= http://www.springframework.org/schema/beans
xmlns:xsi= http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation= http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
bean id= multiFunctionBean >
/beans
利用这个 MultiFunctionBean,我们可以用来探究 Spring 加载 Bean 的多种机制。
doGetBean 方法构造 Bean 流程
上面把 getBean 之外的代码都分析了一下,看代码就可以知道,获取 Bean 对象实例,都是通过 getBean 方法,getBean 方法最终调用的是 DefaultListableBeanFactory 的父类 AbstractBeanFactory 类的 doGetBean 方法,因此这部分重点分析一下 doGetBean 方法是如何构造出一个单例的 Bean 的。
看一下 doGetBean 方法的代码实现,比较长:
protected T T doGetBean(
final String name, final Class T requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
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 +
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we re already creating this bean instance:
// We re assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null !containsBeanDefinition(beanName)) {
// Not found – check parent.
String nameToLookup = originalBeanName(name);
if (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);
}
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It s a prototype – create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException(No Scope registered for scope + scopeName +
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
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);
}
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null bean != null !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
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;
}
关于“Spring 这么初始化 Bean 实例对象”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Spring 这么初始化 Bean 实例对象”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注丸趣 TV 行业资讯频道。