千家信息网

Spring这么初始化Bean实例对象

发表于:2024-10-14 作者:千家信息网编辑
千家信息网最后更新 2024年10月14日,这篇文章主要介绍了Spring这么初始化Bean实例对象的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring这么初始化Bean实例对象文章都会有所收获,下面我们一起
千家信息网最后更新 2024年10月14日Spring这么初始化Bean实例对象

这篇文章主要介绍了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 beanNames = new ArrayList(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() {

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:

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">

利用这个MultiFunctionBean,我们可以用来探究Spring加载Bean的多种机制。

doGetBean方法构造Bean流程

上面把getBean之外的代码都分析了一下,看代码就可以知道,获取Bean对象实例,都是通过getBean方法,getBean方法最终调用的是DefaultListableBeanFactory的父类AbstractBeanFactory类的doGetBean方法,因此这部分重点分析一下doGetBean方法是如何构造出一个单例的Bean的。

看一下doGetBean方法的代码实现,比较长:

protected T doGetBean(

final String name, final Class 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实例对象"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

0