BEAN的加载
通过对于前面的了解,基本上对于Xml配置文件的加载和解析有一个粗略的了解。如果需要详细的了解,可以再结合郝佳编著的《spring源码深度解析》一书相关内容,可以参考着并且编著一些实例。
对于bean的加载的功能可能比bean的解析要 复杂的多。
对于加载bean,这里还是以刚开始的代码:
ApplicationContext context =newClassPathXmlApplicationContext("spring-config.xml");
PetStoreServiceImpl petstore = context.getBean("petstore",PetStoreServiceImpl.class);
这里个getBean()方法,
BeanFactory:Interface(接口)该接口中getBean方法,实现的类是AbstractBeanFactory :
public <T> T getBean(String name, Class<T> requiredType) throwsBeansException {
return doGetBean(name, requiredType, null, false);
}
其中的dogetBean方法:参数name是要获取的bean的name,requiredType为要获取的bean的需要的type,args只有在创建一个原型type时可以使用显示的参数对于一个静态的工厂方法操作,其他任何情形下使用非null的参数都是非法的。Typecheckonly,则是该实例是否止水进行类型的检查,而不是作为实际使用而定的。这里final作为参数变量的修饰符,如果是实际基本数据类型变量,则是在方法内部该变量的副本不允许被改变;如果是对象引用,在方法内部对象引用不能被改变。
@SuppressWarnings("unchecked")
protected <T> TdoGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//(1)这里需要使用BeanFactoryUtils中静态方法对于beanName进行处理
//提取对应的beanName
final String beanName = transformedBeanName(name);
Objectbean;
// Eagerly check singleton cachefor manually registered //singletons.(2)单例bean创建:检查缓存中或者实例工厂中是否有对应的实例。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,spring创建bean的原则是不等bean创建完成,就会将创建bean的ObjectFactory提早曝光,将ObjectFactory加入到缓存中,一旦下个bean创建的时候需要依赖上个bean,则直接使用ObjectFactory,
//直接尝试从缓存获取或者singletonFactories中的ObjectFactory中获取
ObjectsharedInstance= getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if(isSingletonCurrentlyInCreation(beanName)) {
……
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName+ "'");
}
}
//获得beanfactory或者是通过factory获得beanInstance(3),存在BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
bean =getObjectForBeanInstance(sharedInstance, name,beanName,null);
}
else {
//原型模式的依赖检查
// 只有在单例情况下才会尝试解决循环依赖,原型模式情况下,如果我们已经创建了该beaninstance,出现循环引用的情况
//当前beanName是否已经在creation中创建,有的话,抛异常
if(isPrototypeCurrentlyInCreation(beanName)) {
throw newBeanCurrentlyInCreationException(beanName);
}
//(5)检测parentBeanFactory:检查相应的beandefintion是否已经在存在,不存在则尝试从parentBeanFactory中检测
// Check if bean definition exists in this factory.
BeanFactoryparentBeanFactory= getParentBeanFactory();
if (parentBeanFactory!= null&& !containsBeanDefinition(beanName)) {
// Not found -> check parent.
StringnameToLookup= 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);
}
}
//()仅作为类型检查使用,如果不是仅仅做类型检查,则是创建bean,这里要进行记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
//(6)将存储xml配置文件的GenericBeanDefinition转换为RootBeanDefinition,如果指定BEANName是子bean的话,同时合并父类的相关属性(对于beanName相同的beandefintion合并,并进行检查)
try {
final RootBeanDefinition mbd =getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//(7)寻找依赖:初始化当前bean所依赖的bean
String[]dependsOn= mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
//(8)针对不同的scope进行bean的创建,有singleton,prototype ,other
//(8)singleton模式创建bean,创建bean的实例,这里使用了内部类ObjectFactory
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd,args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name,beanName,mbd);
}
//如果不是singleton,而是prototype原型模式
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
ObjectprototypeInstance= null;
try {
beforePrototypeCreation(beanName);
prototypeInstance= createBean(beanName,mbd,args);
}
finally {
afterPrototypeCreation(beanName);
}
bean =getObjectForBeanInstance(prototypeInstance, name,beanName,mbd);
}
//其他bean的获取,这里是指定scope的上面实例化bean
else {
StringscopeName= mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName+ "'");
}
try {
ObjectscopedInstance= scope.get(beanName, newObjectFactory<Object>() {
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 currentthread; " +
"consider defining a scoped proxy for this bean ifyou intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
//(9)类型转换:检查是否需要type match,和实际bean类型是否符合
if (requiredType != null&& bean!= null&& !requiredType.isAssignableFrom(bean.getClass())) {
try {
returngetTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name+ "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw newBeanNotOfRequiredTypeException(name, requiredType,bean.getClass());
}
}
return (T) bean;
}
(1)final String beanName = transformedBeanName(name);转换对应beanName,这里因为传入的参数可能是别名alias,也可能是FactoryBean,(指定了创建bean的方法的factorybean,因为spring的对factorybean的实现有许多个)。
---》跳到抽象AbstractBeanFactory
protected String transformedBeanName(Stringname){
returncanonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils中对于bean,name等处理的静态方法,
(a1)这里是对于&的处理,貌似是过滤掉,原因是?如name=”&createPet” 变成name =”createPet”。
(a2)或者是根据别名alias取得最终的beanName。
(a1):public staticString transformedBeanName(Stringname){
Assert.notNull(name, "'name' must not be null");
StringbeanName= name;
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)){
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
(a2):处理别名alias,通过do…while循环获取到如A->B->C,C这样的最终名称。
publicString canonicalName(String name) {
StringcanonicalName= name;
// Handle aliasing...
StringresolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null){
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
(2)单例注册,尝试从缓存中加载单例
Object sharedInstance = getSingleton(beanName);
--》DefaultSingletonBeanRegistry:
public Object getSingleton(StringbeanName){
return getSingleton(beanName, true);
}获得相应的单例对象,
同时调用如下方法,主要是返回一个bean实例,
protected ObjectgetSingleton(String beanName,booleanallowEarlyReference){
ObjectsingletonObject= 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 != NULL_OBJECT ? singletonObject : null);
}
单例在spring的同一个容器中只会被创建一次,后续再获取bean,就直接从单例缓存中获取。当然这里只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建的时候为了避免循环依赖,在spring中创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光到缓存中,一旦下一个bean创建的时候需要依赖上一个bean则直接使用ObjectFactory。(引用自《spring源码深度解析》)
(3)获得bean实例化对象
如果从缓存中获得了bean的原始状态,还需要对bean进行实例化。缓存中记录的知识最原始的bean状态,并不一定是最终想要的bean。可能它还需要工厂bean中定义的factory-method方法中返回的bean,下面这个方法就是完成这个工作的。
bean =getObjectForBeanInstance(sharedInstance, name,beanName,null);
AbstractBeanFactory:
protected Object getObjectForBeanInstance(
ObjectbeanInstance,String name,String beanName,RootBeanDefinition mbd){
// Don't let calling code try to dereference the factoryif the bean isn't a factory.
//(a)如果bean不是一个factory,则会抛出异常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw newBeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 现在我们是有了一个bean实例,也可能是一个factorybean.
//如果不是一个factorybean的话,我们可以使用工厂的引用来创建一个bean instance。
if (!(beanInstance instanceof FactoryBean) ||BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Objectobject= null;
if (mbd == null) {//从缓存对象中获得factorybean
object =getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?>factory= (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is asingleton.//对于相同beanName的beandefinition进行合并(root child)
if (mbd == null &&containsBeanDefinition(beanName)) {
mbd =getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object =getObjectFromFactoryBean(factory, beanName,!synthetic);
}
return object;
}
(4) 原型模式的依赖检查
只有在单例情况下才会尝试解决依赖。如果实在原型模式的如果存在依赖的话,则抛出异常。
(5)检测parentBeanFactory
(6)将存储xml配置文件的genericBeanDefintion转换成RootBeanDefinition。
(7)需找依赖
(8)针对不同的scope进行bean的创建
(9)类型装换
下面分别进行讲解:
5.1FactoryBean的使用
Bean的实例化,是通过配置文件提供的class通过反射机制实现的。复杂的bean则需要配置方式也复杂一些。这是采用编码的方式会得到一个简单的解决方案。Spring为此提供了一个org.spingframework.bean.factory.FactoryBean的工厂类接口,用户通过实现该接口定制实例化自己的bean的逻辑。(摘自《spring源码深度分析》)
可以看到该接口中定义的三个方法,
T getObject()返回有FactoryBean创建的bean实例,如果是isSingleton()true,则该实例会放到spring容器中单实例缓冲池中。
Boolean isSingleton()返回有factorybean创建的bean实例的作用域是singleton还是prototype。
Class<T> getObjectType()返回factorybean创建的bean类型。
下面是smartfactorybean接口继承自factorybean接口。
当配置文件中<bean>的class属性配置的实现类是factorybean时,通过getBean()方法返回的不是FactoryBean本身,而是factorybean#getObject()方法返回的对象,相当于factorybean#getObject()代理了getBean()方法。
个人觉得《spring源码深度解析》中那个利用getObject()方法,写的carFactoryBean的例子很好的给我们介绍了一个XXXFactoryBean类的实现,并简单的获取到相应的bean。
该例子:
#class:CarInfo
public classCarInfo {
private String name ;
private double price;
private String brand;
public CarInfo(){
}
public CarInfo(String name,double price,String brand){
this.name = name;
this.price = price;
this.brand = brand;
}
//get set method
……
}
#class:CarFactoryBean
public classCarFactoryBean implementsFactoryBean<CarInfo> {
private String carMessage;
@Override
public CarInfo getObject() throws Exception {
// TODO Auto-generated method stub
CarInfocar= newCarInfo();
String[] message= carMessage.split(",");
car.setBrand(message[0]);
car.setName(message[1]);
car.setPrice(Double.parseDouble(message[2]));
return car;
}
@Override
public Class<CarInfo>getObjectType() {
// TODO Auto-generated method stub
return CarInfo.class;
}
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return false;
}
public String getCarMessage(){
return carMessage;
}
public void setCarMessage(String carMessage) {
this.carMessage = carMessage;
}
}
配置文件中:
<bean id="carFactoryBean" class="com.springframework.samples.jpetstore.myfactorybean.CarFactoryBean">
<property name="carMessage"value ="dazhong,sangtna2000,20.2" />
</bean>
#test:
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
CarInfo car = (CarInfo)bf.getBean("carFactoryBean");
System.out.println("Brand:"+car.getBrand()+" ,Name: "+car.getName()+",Price: "+car.getPrice());
CarFactoryBean carFactoryBean = (CarFactoryBean) bf.getBean("&carFactoryBean");
System.out.println(carFactoryBean.getCarMessage());
该xxxFactoryBean的getObject()方法只是模拟给出一个类似的bean。
5.2缓存中获取单例bean
下面介绍bean的加载,前面已经提到过单例在spring的同一容器中只会被创建一次,后续再获得bean直接从单例缓存中获得。当然这也是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,spring创建bean的原则是不等bean创建完成就会将bean的objectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则世界使用ObjectFactory.
Object sharedInstance = getSingleton(beanName);
--》DefaultSingletonBeanRegistry:
public Object getSingleton(StringbeanName){
//true参数允许早期依赖
return getSingleton(beanName, true);
}获得相应的单例对象,
同时调用如下方法,主要是返回一个bean实例,----》
protected ObjectgetSingleton(String beanName,booleanallowEarlyReference){
//检查缓存中是否存在实例
ObjectsingletonObject= this.singletonObjects.get(beanName);
//如果为空则锁定全局变量进行处理
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//如果此bean正在加载则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference){
//当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略储存在singletonFactories中
ObjectFactory<?>singletonFactory= this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
首先从singletonObjects中获取,如果不成功,则利用尝试从earlySingletonObjects中获取,如果仍然不成功,则从singletonFactories中获取singletonFactory,调用该beanName的ObjectFactory再通过方法getObject()获得object对象(即创建bean),并放到earlySingletonObjects中,并且从singletonFactories中remove掉该ObjectFacotry。
这里几个map集合:
singletonObjects:用于保存BEANName和创建bean实例之间的关系,beanname------beaninstance
singletonFactories :用于保存beanName和创建bean的工厂之间的关系
earlySingletonObjects:保存beanName和创建bean实例之间的关系,与singletonObjects的不同之处是它可以在bean还在创建过程中,就可以通过getBean()方法或得到。
5.3获得实例化bean对象:
在getBean方法中,getObejctForBeanInstance是个高频了的使用的方法,可以从代码中看到从缓存中获取bean,还是根据不同的scope策略来加载bean。
从得到bean实例后要做的是调用该方法验证一下其正确性与否,检测当前bean是否是factorybean类型的bean,还是普通的bean。如果类型时factorybean,需要调用该bean对应的factorybean实例中的getObject()方法作为得到bean返回值。
同时得到的bean,是原始的,有些需要进行加工处理。真正需要的有时是factorybean中定义的factory-method方法返回的bean,而getObejctForBeanInstance方法就是完成这个操作的。
其中的内容是:bean =getObjectForBeanInstance(sharedInstance, name,beanName,null);
AbstractBeanFactory:
protected Object getObjectForBeanInstance(
ObjectbeanInstance,String name,String beanName,RootBeanDefinition mbd){
//(a)如果bean不是一个factorybean类型,且指定的那么是工厂相关(以&前缀),则会抛出异常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw newBeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 现在我们是有了一个bean实例,也可能是一个factorybean.
//如果不是一个factorybean的话,我们可以使用工厂的引用来创建一个bean instance。但是如果用户想要获得相应的factorybean实例问不是工厂的getObject方法对应的实例,那么可以传入的name应该是加入了前缀&的.
if (!(beanInstance instanceof FactoryBean) ||BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Objectobject= null;
if (mbd == null) {//从缓存对象中获得factorybean
object =getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?>factory= (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is asingleton.//对于相同beanName的beandefinition进行合并(root child)
if (mbd == null &&containsBeanDefinition(beanName)) {
//将存储xml配置文件的GenericBeanDefinition装换为RootBeanDefinition,如果指定beanName是子bean的话同时会合并父类的相关属性
mbd =getMergedLocalBeanDefinition(beanName);
}
//是否是用户定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
object =getObjectFromFactoryBean(factory, beanName,!synthetic);
}
return object;
}
其核心的代码则是 object= getObjectFromFactoryBean(factory, beanName,!synthetic);
FactoryBeanRegistrySupport:getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?>factory,String beanName,booleanshouldPostProcess){
//如果是单例模式,则使用缓存中的beanName
if (factory.isSingleton()&& containsSingleton(beanName)) {
synchronized(getSingletonMutex()) {
Objectobject= this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object =doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there alreadyduring getObject() call above
// (e.g. because of circular reference processingtriggered by custom getBean calls)
ObjectalreadyThere= this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess){
try {
object =postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton objectfailed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT? object: null);
}
}
else {
Objectobject= doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess){
try {
object =postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's objectfailed", ex);
}
}
return object;
}
}
真正的方法在doGetObjectFromFactoryBean()中:
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Objectobject;
try {//权限验证
if (System.getSecurityManager()!= null){
AccessControlContextacc= getAccessControlContext();
try {
object = AccessController.doPrivileged(newPrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
return factory.getObject();
}
},acc);
}
catch(PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
catch(FactoryBeanNotInitializedException ex) {
throw newBeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on objectcreation", ex);
}
// Do not accept a null value for a FactoryBean that'snot fully
// initialized yet: Many FactoryBeans just return nullthen.
if (object == null &&isSingletonCurrentlyInCreation(beanName)) {
throw newBeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returnednull from getObject");
}
return object;
}
其中factory.getObject()就是我们想要的,工厂中得到了对象。
其实在doGetObjectFromFactoryBean()之后,得到了object之后,进行了一下后处理:postProcessObjectFromFactoryBean
Objectobject= doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess){
try {
object =postProcessObjectFromFactoryBean(object, beanName);
跟踪来到
AbstractAutowireCapableBeanFactory:
protected Object postProcessObjectFromFactoryBean(Objectobject,String beanName){
returnapplyBeanPostProcessorsAfterInitialization(object, beanName);
}
其中方法:
public Object applyBeanPostProcessorsAfterInitialization(ObjectexistingBean,String beanName)
throws BeansException {
Objectresult= existingBean;
for (BeanPostProcessor beanProcessor :getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
先到此。Spring中获取bean的规则:尽可能保证所有bean初始化后都会调用注册的BEANPostProcessor的postProcessAfterInitialization进行处理。
其实到这里还是有些晕晕的,获得bean,不是获得了吗?之前应该是从已经存在缓存中获取的bean,或者是尝试使用factorybean,有些时候说的bean,可能是相应的xxxFactoryBean,可以通过其ObjectFactory的getObject获得对象bean。这里只讲了对于(1)beanName的处理;(2)从缓存中加载bean,此时bean的状态时初始的,还需要进一步处理;(3)对于bean的进一步处理,经由xxxObjectFactory的getObject方法返回特定处理的bean。-----------------------------------未完待续2