在之前介绍了Spring IOC 容器在项目中的作用
源码介绍之前,看几个问题:
spring.xml文件中保存了我们对Bean的描述配置,BeanFactory会读取这些配置然后生成对应的Bean。
这些配置信息最后由BeanDefinition来承载。
IOC实现中,我们在xml中的描述的Bean信息最后都将保存至BeanDefinition对象中,其中xml bean与BeanDefinition是一对一的关系。
xml bean的属性配置与BeanDefinition对应关系
XML-Bean | BeanDefinition |
---|---|
class | beanClassName |
scope | SCOPE_SINGLETON、SCOPE_PROTOTYPE |
lazy-init | AbstractBeanDefinition.lazyInit |
constructor-arg | AbstractBeanDefinition.ConstructorArgument |
property | AbstractBeanDefinition.propertyValues |
factory-method | AbstractBeanDefinition.factoryMethondName |
destroy-method | AbstractBeanDefinition.destroyMethodName |
init-method | AbstractBeanDefinition.initMethodName |
autowire | AbstractBeanDefinition.autowireMode |
id | |
name |
BeanDefinition.java
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
...
}
AbstractBeanDefinition.java
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
public static final String SCOPE_DEFAULT = "";
public static final int AUTOWIRE_NO = 0;
public static final int AUTOWIRE_BY_NAME = 1;
public static final int AUTOWIRE_BY_TYPE = 2;
public static final int AUTOWIRE_CONSTRUCTOR = 3;
/** @deprecated */
@Deprecated
public static final int AUTOWIRE_AUTODETECT = 4;
public static final int DEPENDENCY_CHECK_NONE = 0;
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
public static final int DEPENDENCY_CHECK_ALL = 3;
public static final String INFER_METHOD = "(inferred)";
private volatile Object beanClass;
private String scope;
private boolean abstractFlag;
private boolean lazyInit;
private int autowireMode;
private int dependencyCheck;
private String[] dependsOn;
private boolean autowireCandidate;
private boolean primary;
private final Map<String, AutowireCandidateQualifier> qualifiers;
private boolean nonPublicAccessAllowed;
private boolean lenientConstructorResolution;
private String factoryBeanName;
private String factoryMethodName;
private ConstructorArgumentValues constructorArgumentValues;
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides;
private String initMethodName;
private String destroyMethodName;
private boolean enforceInitMethod;
private boolean enforceDestroyMethod;
private boolean synthetic;
private int role;
private String description;
private Resource resource;
...
}
BeanDefinitionRegistry(Bean注册器) 在上面没有看到xml bean中的id、name属性对应在bean定义中,原因是id其作为当前bean的存储key注册到BeanDefinitionRegistry注册器中。name作为别名key注册到AliasRegistry注册中心。其最后都是指向对象的BeanDefinition。
BeanDefinitionRegistry.java
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String var1);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String var1);
}
AliasRegistry.java
public interface AliasRegistry {
void registerAlias(String var1, String var2);
void removeAlias(String var1);
boolean isAlias(String var1);
String[] getAliases(String var1);
}
BeanDefinitionReader(Bean定义读取) 前面知道了BeanDefinition存储了xml bean信息,而BeanDefinitionRegistry基于id和name保存bean的定义,下面是xml bean到BeanDefinition然后注册到BeanDefinitionRegistry整个过程。
分为3步:
1、BeanDefinitionReader读取spring.xml
2、读取后创建BeanDefinition
3、创建好后注册到BeanDefinitionRegister
BeanDefinitionReader.java
public interface BeanDefinitionReader {
//获取注册器
BeanDefinitionRegistry getRegistry();
//获取资源装载器
ResourceLoader getResourceLoader();
//获取bean类加载器
ClassLoader getBeanClassLoader();
BeanNameGenerator getBeanNameGenerator();
//基于资源装载Bean定义并注册到注册器
int loadBeanDefinitions(Resource var1) throws BeanDefinitionStoreException;
int loadBeanDefinitions(Resource... var1) throws BeanDefinitionStoreException;
//基于资源路径装载Bean定义并注册到注册器
int loadBeanDefinitions(String var1) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String... var1) throws BeanDefinitionStoreException;
}
装载过程demo
package com.demo.spring;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import java.util.Arrays;
/**
* com.demo.spring
*
* @author Zyy
* @date 2019/2/13 11:34
*/
public class BeanDefinitionReaderTest {
public static void main(String[] args) {
//创建一个简单注册器
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
//创建bean定义读取器
BeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
//创建资源读取器
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
//获取资源
Resource resource = resourceLoader.getResource("spring.xml");
//装载类定义
reader.loadBeanDefinitions(resource);
//打印构建bean名称
System.out.println(Arrays.toString(registry.getBeanDefinitionNames()));
}
}
运行结果
[di, driver, com.demo.spring.HelloSpring#0, com.demo.spring.LookUpTest#0, helloSpring, com.demo.spring.DI#1, com.demo.spring.DI#0, helloByName]
如果未给bean设置id则:class+#+索引,来标识id
com.demo.spring.HelloSpring#0
打印一下bean定义信息
spring.xml
<bean id="di" name="di2" lazy-init="false" class="com.demo.spring.DI" scope="singleton" init-method="init" destroy-method="destroy"/>
打印语句:
System.out.println(registry.getBeanDefinition("di"));
System.out.println(registry.getAliases("di2"));
结果信息:
Generic bean: class [com.demo.spring.DI]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=init; destroyMethodName=destroy; defined in class path resource [spring.xml]
[Ljava.lang.String;@73a28541
有了Bean的定义,则下面可以用BeanFactory来进行构建bean。
BeanFactory.java
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
//基于id或name获取一个bean
Object getBean(String name) throws BeansException;
//基于bean的类别获取bean(如果出现多个该类的实例,则会报错)但是可以指定primary="true"调整优先级来解决该报错
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
//基于名词获取一个bean,并覆盖默认的构造参数
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//指定bean与指定class是否匹配
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
测试demo如下:
package com.demo.spring;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;
/**
* com.demo.spring
*
* @author Zyy
* @date 2019/2/13 12:19
*/
public class BeanFactoryTest {
public static void main(String[] args) {
//注册中心
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//读取器
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
//设置资源加载器
reader.setResourceLoader(new DefaultResourceLoader());
//装载构建bean的定义
reader.loadBeanDefinitions("spring.xml");
//打印
System.out.println(beanFactory.getBean("di"));
System.out.println(beanFactory.getBean("di2"));
}
}
当getBean时,看下堆栈信息,如下
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
- locked <0x593> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at com.demo.spring.BeanFactoryTest.main(BeanFactoryTest.java:25)
看具体调用方法
instantiateClass:142, BeanUtils (org.springframework.beans)
instantiate:89, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiateBean:1147, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1099, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:513, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:306, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:302, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
main:25, BeanFactoryTest (com.demo.spring)
逐个点进去查看
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
AbstractBeanFactory#getBean中继续调用doGetBean,查看doGetBean,由于其中代码太多,删除检查判断,只保留核心代码
org.springframework.beans.factory.support.AbstractBeanFactory#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) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 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);
}
try {
// Create bean instance.
//mbd -> RootBeanDefinition
//判断是否单例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException 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 name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
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) {
...
}
}
}
catch (BeansException ex) {
...
}
}
return (T) bean;
}
其中
Object sharedInstance = getSingleton(beanName);
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//如果取到的为null且判断是正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//则锁住map
synchronized (this.singletonObjects) {
//从正在创建的earlySingletonObjects这个map中去取
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);
}
其中singletonObjects、earlySingletonObjects、singletonFactories均是一个map
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
对于其中的
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
其中如果是FactoryBean,则调用getObject()来获取我们自定义的bean,例如
<!-- FactoryBean创建 自定义创建bean-->
<bean id="driver" class="com.demo.spring.DriverFactoryBean" >
<property name="jdbcUrl" value="jdbc:mysql://192.168.5.104:3306"></property>
</bean>
其中返回的不是DriverFactoryBean,而是返回Driver
public Class<?> getObjectType() {
return Driver.class;
}
总结:
1、调用BeanFactory.getBean()会触发Bean的实例化。
2、DefaultSingletonBeanRegistry中缓存了单例Bean。
3、Bean的创建于初始化是由AbstractAutowireCapableBeanFactory完成的。
另外:
IOC容器只存放单例Bean,IOC容器在初始化的时候,会将所以Bean初始化在singletonObjects这个ConcurrentHashMap中。 在获取bean的时候,首先会去singletonObjects中去取,如果scope是单例则可以获取bean,如果是多例,则取不到bean,需要从mergedBeanDefinitions这个ConcurrentHashMap中获取RootBeanDefinition,这个里面包含bean的基础信息,然后判断scope是prototype(多例),则每次都会创建一个新的实例。
对于@Autowire、@Resource等注解,在启动SpringIOC容器时,容器会装载一个AutowiredAnnotationBeanPostProcessor 后置处理器,当容易扫描到@Autowire、@Resource等注解时,就会在IOC容器中自动查找需要的Bean,并装配给该对象的属性,在使用@Autowire时,首先在容器中查询对应类型的bean,如果查询不止一个,则根据名称来查,如果名称没有则抛异常,可以将required=false来解决,如果正好查询到一个,则就将该bean装配给@Autowire指定的变量。
对于bean之间相互引用的情况,比如A依赖B,B依赖A,这种情况时,先去实例化A,然后发现依赖B,接着去实例化B,如果此时发现B依赖A,容器会获取A的一个早期引用(early reference),将这个早期引用的A注入给B,然后B实例化完了,则实例化A也就完成了。当然对于这种循环引用的代码应该规避,这种不是正常的场景。
涉及的类:
BeanDefinition
DefaultResourceLoader
XmlBeanDefinitionReader
BeanDefinitionRegistry
BeanFactory
DefaultListableBeanFactory
AutowireCapableBeanFactory
AbstractAutowireCapableBeanFactory
SingletonBeanRegistry
DefaultSingletonBeanRegistry
整个流程:
run->getBean->BeanFactory->doGetBean->AbstructBeanFactory
->getSingleton(从缓存中获取,如果是单例,为空则创建并缓存,如果是多例则直接创建)
->DefaultSingleonBeanRegistry->createBean->AbstractAutowireCapableBeanFactory
->createBeanInstance->newInstance->Constructor->反射实例化Bean
看下结构图
ApplicationContext.java
ApplicationContext.png
从图中可以看到ApplicationContext是由BeanFactory接口派生出来的,具有BeanFactory所以功能。除此之外,还具有以下功能:
1、MessageSource,提供国际化的消息访问
2、资源访问,入url和文件
3、事件传播,实现了ApplicationListener接口的bean
4、载入多个上下文(有继承关系),使每个上下文都专注于一个特定的层次,比如应用web层
类似的
DefaultListableBeanFactory.java
DefaultListableBeanFactory.png
github地址 : https://github.com/zhaoyybalabala/spring-test
如有问题,欢迎提问:)