1、示例POJO类
用户类User,其中包含一个狗的引用
package org.springframework.cn.shu.edu.pojo;
public class User {
String username;
String password;
Dog dog;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
狗类
package org.springframework.cn.shu.edu.pojo;
public class Dog {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2、工程结构
3、spring配置文件beans.xml
其中配置了一个Dog类的对象,一个User类的对象。
4、测试代码
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.cn.shu.edu.pojo.User;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class Test1 {
public static void main(String[] args) {
Resource res = new ClassPathResource("beans.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
User chenjie = factory.getBean("chenjie", User.class);
System.out.println(chenjie.getUsername());
User chenjie2 = factory.getBean("chenjie", User.class);
System.out.println(chenjie2.getDog().getName());
}
}
其中,首先定义了一个资源,指定从classpath下加载beans.xml文件,然后新建了一个DefaultListableBeanFactory的工厂对象,然后新建了一个XmlBeanDefinitionReader的Xml类定义读取器,接着使用该读取器加载bean定义。
随后便可以使用创建的工厂了,我们调用两次getBean。
首先观看输出:
可以看到User类中的Dog类对象的引用两次都没有找到,而User类第一次没有找到,第二次找到了。我们将分析整个过程。
5、
Resource res = new ClassPathResource("beans.xml");
此句新建了一个ClassPathResource对象,用beans.xml作为参数。看看ClassPathResource的类图
Resource是Spring用来封装IO操作的类。在这里我们的BeanDefinition信息是以xml文件形式存在的。
这句代码首先调用了一个参数的构造函数,参数为bean定义的配置文件的路径
public ClassPathResource(String path) {
this(path, (ClassLoader) null);
}
可以看到它又调用了两个参数的构造函数,其中第二个参数为ClassLoader类型,这里由于此前没有指定ClassLoader是谁,因此设置为空。
再看看两个参数的构造函数
public ClassPathResource(String path, ClassLoader classLoader) {
//判空
Assert.notNull(path, "Path must not be null");
//清洗路径
String pathToUse = StringUtils.cleanPath(path);
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
this.path = pathToUse;
//得到classLoader
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}
首先由于必须给定配置文件的路径,因此使用了断言来判空。
然后使用StringUtils工具类的cleanPath方法进行路径的整理。
public static String cleanPath(String path) {
if (path == null) {
return null;
}
String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);
// Strip prefix from path to analyze, to not treat it as part of the
// first path element. This is necessary to correctly parse paths like
// "file:core/../core/io/Resource.class", where the ".." should just
// strip the first "core" directory while keeping the "file:" prefix.
int prefixIndex = pathToUse.indexOf(":");
String prefix = "";
if (prefixIndex != -1) {
prefix = pathToUse.substring(0, prefixIndex + 1);
pathToUse = pathToUse.substring(prefixIndex + 1);
}
if (pathToUse.startsWith(FOLDER_SEPARATOR)) {
prefix = prefix + FOLDER_SEPARATOR;
pathToUse = pathToUse.substring(1);
}
String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);
List pathElements = new LinkedList();
int tops = 0;
for (int i = pathArray.length - 1; i >= 0; i--) {
String element = pathArray[i];
if (CURRENT_PATH.equals(element)) {
// Points to current directory - drop it.
}
else if (TOP_PATH.equals(element)) {
// Registering top path found.
tops++;
}
else {
if (tops > 0) {
// Merging path element with element corresponding to top path.
tops--;
}
else {
// Normal path element found.
pathElements.add(0, element);
}
}
}
// Remaining top paths need to be retained.
for (int i = 0; i < tops; i++) {
pathElements.add(0, TOP_PATH);
}
return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR);
}
整理完成以后,判断路径是否以/开头,如果是/开头,则表示是相对于classpath是根目录,所以用/后面的作为路径。
然后判断classloader是否为空,如果传入的不为空则使用之,如果为空,则调用ClassUtils.getDefaultClassLoader()来获取默认的ClassLoader,其方法如下。
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back to system class loader...
}
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = ClassUtils.class.getClassLoader();
}
return cl;
}
首先尝试得到当前线程的上下文的ClassLoader,如果获取失败会抛出异常,cl为空,则会获取ClassUtil类对象的ClassLoader并返回。
6、
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
首先看看DefaultListableBeanFactory的类图。
可以看到是一个相对复杂的继承关系。
首先调用DefaultListableBeanFactory类的无参构造函数。
/**
* Create a new DefaultListableBeanFactory.
*/
public DefaultListableBeanFactory() {
super();
logger.info("初始化DefaultListableBeanFactory完成");
}
可以看到什么都没有做,只是调用了父类的无参构造函数。我们来看看它的父类AbstractAutowireCapableBeanFactory的无参构造函数。
/**
* Create a new AbstractAutowireCapableBeanFactory.
*/
public AbstractAutowireCapableBeanFactory() {
super();
logger.info("初始化AbstractAutowireCapableBeanFactory()完成");
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
可以看到其调用了父类的无参构造函数,接着调用了三次ignoreDependencyInterface方法,该方法其作用是指定自动装配(autowiring)的时候忽略的接口。这里我们先不做讨论。
https://www.jianshu.com/p/3c7e0608ff1f
我们来看看其调用的父类AbstractBeanFactory的无参构造函数
/**
* Create a new AbstractBeanFactory.
*/
public AbstractBeanFactory() {
logger.info("初始化AbstractBeanFactory()完成");
}
其中什么都没有做。到这里没有再显式地调用父类的构造函数,事实上,当我们再看AbstractBeanFactory的父类FactoryBeanRegistrySupport,FactoryBeanRegistrySupport的父类DefaultSingletonBeanRegistry,DefaultSingletonBeanRegistry的父类SimpleAliasRegistry的源码会发现其都没有写构造方法,也就是说其都是默认的空的无参构造函数。
7、
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
这里新建一个XmlBeanDefinitionReader对象,并以此前创建的DefaultListableBeanFactory的对象factory作为参数。
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
logger.info("初始化XmlBeanDefinitionReader()完成");
}
再看其构造器,发现需要的参数只需要实现BeanDefinitionRegistry 接口即可,观察类图或者查看源码可知DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {}
该接口中有bean定义数量和bean定义名称两个属性,有注册bean定义、移除bean定义,得到bean定义、判断是否包含bean定义、bean名称是否在使用等方法。
XmlBeanDefinitionReader调用了父类的构造器如下:
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// Determine ResourceLoader to use.
if (this.registry instanceof ResourceLoader) {
logger.info("this.registry instanceof ResourceLoader" );
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
logger.info("this.registry is not instanceof ResourceLoader" );
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
}
首先进行必要的判空和赋值,然后判断传入的参数(这个registry对象参数肯定实现了BeanDefinitionRegistry ,但是否实现了ResourceLoader未知)是否实现了ResourceLoader。
我们这里传入的DefaultListableBeanFactory对象没有实现这个接口,因此在else里面,会新建一个PathMatchingResourcePatternResolver对象。
ResourceLoader提供 classpath下单资源文件的载入,而ResourcePatternResolver提供了多资源文件的载入。ResourcePatternResolver有一个实现类:PathMatchingResourcePatternResolver
我们这里新建了一个PathMatchingResourcePatternResolver对象。我们先不深入。
7、
reader.loadBeanDefinitions(res);
这里使用了XmlBeanDefinitionReader类的loadBeanDefinitions方法加载Resource类的对象res。
/**
* Load bean definitions from the specified XML file.
* @param resource the resource descriptor for the XML file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
logger.info("进入loadBeanDefinitions(Resource resource)");
return loadBeanDefinitions(new EncodedResource(resource));
}
这里首先将resource进行encode,作用是进行编码。然后我们看看loadBeanDefinitions的具体实现。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
logger.info("进入loadBeanDefinitions(EncodedResource encodedResource)");
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
进行必要的判空后,首先使用
Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
XmlBeanDefinitionReader内部维护了一个resourcesCurrentlyBeingLoaded变量,用于保存最近被加载的资源。
private final ThreadLocal> resourcesCurrentlyBeingLoaded =
new NamedThreadLocal>("XML bean definition resources currently being loaded");
如果为空,则进行必要的初始化。
然后将传入的参数加入currentResources中,紧接着得到资源里面的输入流(public interface Resource extends InputStreamSource):
InputStream inputStream = encodedResource.getResource().getInputStream();
然后将输入流封装成了org.xml.sax库的InputSource对象,这里完成对xml的解析的加载过程。然后进行编码设置。
接着调用了doLoadBeanDefinitions(inputSource, encodedResource.getResource());方法。
做完以后关闭流,最后将传入的资源从最近被加载的资源中删除。
我们来看看doLoadBeanDefinitions方法的实现。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
return registerBeanDefinitions(doc, resource);
}
//....
}
其中涉及validationMode验证模式,可以参考https://blog.csdn.net/nangongyanya/article/details/53887467
然后使用this.documentLoader.loadDocument方法来加载xml文档。documentLoader是DefaultDocumentLoader类的对象。
private DocumentLoader documentLoader = new DefaultDocumentLoader();
让我们来看看DefaultDocumentLoader类的loadDocument方法。
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}
它有几个参数,分别是输入源inputSource,实体解析器entityResolver,错误处理器errorHandler,XML验证模式validationMode,namespaceAware。最终落实到DocumentBuilder的parse方法。
接着调用registerBeanDefinitions(doc, resource);
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// Read document based on new BeanDefinitionDocumentReader SPI.
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
其中createBeanDefinitionDocumentReader方法主要新建了一个BeanDefinitionDocumentReader 接口的实现类DefaultBeanDefinitionDocumentReader然后调用其registerBeanDefinitions方法
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.info("---->Loading bean definitions at " + DefaultBeanDefinitionDocumentReader.class.getSimpleName());
Element root = doc.getDocumentElement();
logger.info("--->root:" + root.getTagName());
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
preProcessXml(root);
parseBeanDefinitions(root, delegate);
postProcessXml(root);
}
其中root代表了xml文档的根元素,可以增加打印语句看看:
从输出可以看到其根元素为
接着Bean定义解析代理类BeanDefinitionParserDelegate的对象,由它解析根元素中的内容,对于根元素前和跟元素后的内容,则由preProcessXml和postProcessXml两个方法完成,目前为空实现。我们来看看parseBeanDefinitions方法。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
首先判断是否是默认的命名空间,如果是,则执行parseDefaultElement,否则执行parseCustomElement。
我们这里是使用的默认的命名空间,因此接着调用getChildNodes方法获得
然后对于每个子节点,根据当前是否是默认命名空间来调用不同方法解析。
我们这里先只看parseDefaultElement。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
}
这里分了3种情况,分别是节点标签名对应import alias 和bean的情况。
它们分别处理
我们这里只涉及bean的解析。来看看。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
/***
* BeanDefinitionHolder是BeanDefinition对象的封装类,封装了BeanDefinition,Bean的名字和别名。用它来完成向IoC容器注册。
* 得到这个BeanDefinition实际上就意味着获得了BeanDefinition,是通过BeanDefinitionParserDelegate对XML元素的信息按照
* Spring的Bean规则进行解析得到的
*/
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 这里是向IoC容器注册解析得到的BeanDefinition的地方。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
BeanDefinitionHolder是BeanDefinition的封装。
而BeanDefinition可以看成是
可以看到其中包含关于类名、原型、延迟加载、单例、依赖的方法。
具体的加载过程由BeanDefinitionParserDelegate对XML元素的信息按照Spring的Bean规则进行解析得到的,入口是
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean){}
其中会调用parseBeanDefinitionElement方法。
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
logger.info("\tgo into parseBeanDefinitionElement of beanName :" + beanName);
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
logger.info("\tclass =" + className);
}
try {
String parent = null;
//如果元素有parent属性
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
//得到parent节点
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
//根据parent创建AbstractBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析bean定义
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//为bean定义设置描述
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造器参数元素
parseConstructorArgElements(ele, bd);
//解析属性元素
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
其中createBeanDefinition创建一个BeanDefinition的实现GenericBeanDefinition。然后调用parseConstructorArgElements、parsePropertyElements等解析构造器参数,解析属性元素等。
createBeanDefinition中直接使用BeanDefinitionReaderUtils.createBeanDefinition创建bean。
public static AbstractBeanDefinition createBeanDefinition(
String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else {
bd.setBeanClassName(className);
}
}
return bd;
}
其中使用了ClassUtils加载类的定义,然后为BeanDefinition设置了bean的class属性。
parsePropertyElements中循环调用了多次parsePropertyElement来处理每个property
然后回到:DefaultBeanDefinitionDocumentReader
解析bean定义后,使用如下方法注册bean定义,这里的getReaderContext().getRegistry()就是最开始新建的工厂对象DefaultListableBeanFactory。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
主要代码如下,即调用registerBeanDefinition方法。
该方法主要是往一个并发HashMap中写入刚刚注册得到的bean定义
private final Map beanDefinitionMap = new ConcurrentHashMap();
由此,便将bean名字到bean定义的映射保存在了DefaultListableBeanFactory中。
8、
User chenjie = factory.getBean("chenjie", User.class);
这里调用了DefaultListableBeanFactory的getBean方法,但该方法是从父类AbstractBeanFactory继承而来。
public T getBean(String name, Class requiredType) throws BeansException {
logger.info("AbstractBeanFactory getBean,name=" + name + ",requiredType=" + requiredType);
return doGetBean(name, requiredType, null, false);
}
直接调用doGetBean
protected T doGetBean(
final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
logger.info("AbstractBeanFactory doGetBean,name=" + name + ",requiredType=" + requiredType);
final String beanName = transformedBeanName(name);
logger.info("transformedBeanName, beanName=" + beanName);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//先从缓存中去取,处理已经被创建过的单件模式的bean,对这种bean的请求不需要重复地创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
logger.info("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 + "'");
}
}
/***
* 这里的getObjectForBeanInstance完成的是FactoryBean的相关处理,
* 以取得FactoryBean的生产结果,BeanFactory和FactoryBean的区别
* 会在这个过程中详细地分析
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
logger.info("sharedInstance == null || args != null");
// 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.
/**
* 这里对IoC容器里的BeanDefinition是否存在进行检查,检查是否能在当前的BeanFactory中取到我们需要的bean。
* 如果在当前的工厂中取不到,则到双亲BeanFactory中去取;
* 如果当前的双亲工厂取不到,那就顺着双亲BeanFactory链一直向上查找
*/
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);
}
//这里根据bean的名字取得BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
/***
* 取当前bean的所有依赖bean,这样会触发getBean的递归调用,直至取到一个没有任何依赖的bean为止。
*/
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
// Create bean instance.
/***
* 这里创建Singleton bean的实例,通过调用crateBean方法,这里有个回调函数getObject,
* 会在getSingleton中调用ObjectFactory的createBean
*/
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);
}
//这里是创建prototype bean的地方
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.
/***
* 这里对创建出来的bean进行类型检查,如果没有问题,就返回这个新创建出来的bean,
* 这个bean已经是包含了依赖关系的bean
*/
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;
}
总结: