简介
bean加载的实现比bean的解析更要复杂,对于加载bean的功能,在Spring中的调用方式为:
MyTestBean myTestBean = (MyTestBean) xmlBeanFactory.getBean("demo");
我们先跟踪代码快速体验一下Spring 中代码是如何实现的。
AbstractBeanFactory.java
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 提取对应的 beanName
final String beanName = transformedBeanName(name);
Object bean;
/**
*检查缓存中或者实例工厂中是否有对应的实例,为什么首先会使用这段代码那?
*因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,
* Spring创建bean的原则是不等bean创建完成就会将创建bean的 ObjectFactory提早曝光
* 也就是将ObjectFactory 加入到缓冲中,一旦下个bean创建时候需要依赖上个bean,则直接使用ObjectFactory
*/
// 直接尝试从缓存中获取或者 singletonFactories 中的 ObjectFactory 中获取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 返回对应的实例,有时候sharedInstance存在诸如 BeanFactory 的情况并不是返回实例本身,而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 判断指定的原型bean是否在创建中,因为原型的bean是无法解决循环依赖的,所以抛出异常
// 只有在单例的情况才会尝试解决循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果beanDefinitionMap 中也就是所有已经加载的类中不包括 beanName, 则尝试从 parentBeanFactory 中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
// 递归到 beanFactory 中寻找
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不是仅仅做类型检查则是创建bean, 这里要进行记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 将存储XML配置文件的GernericBeanDefinition 转换为RootBeanDefinition,
// 如果指定beanName 是子Bean的话同时会合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 获取当前bean所依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存依赖调用
registerDependentBean(dep, beanName);
try {
// 实例化所依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 实例化依赖的bean 后便可以实例化mbd 本身了
// singleton 模式的创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
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 模式的创建
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 {
// 根据自定的scope 实例化bean
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, () -> {
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);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 检查需要的类型是否符合bean的实际类型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
有没有看晕那,哈哈,从代码量上看出是相当复杂的,做了非常多的判断,参考部门代码注释,可以初略的了解整个Spring的加载bean的过程。
- 转换
beanName
- 尝试从缓存中获取单例
- 合并Bean 定义,递归对父类的定义进行合并和覆盖
- 原型依赖的检查
- 检查
parentBeanFactory
- bean的实例化
- 类型转换
转换beanName
// 转换 beanName
final String beanName = transformedBeanName(name);
我们解析完配置后创建的Map, 使用的是 beanName 作为key。
DefaultListableBeanFactory.java
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
BeanFactory.getBean(“name”) 中传入的name,有以下几种可能:
beanName
: 可以直接获取到定义的BeanDefinition
。alias name
: 别名,需要转化.factoryBean name
, 带&
前缀,通过它获取BeanDefinition
的时候需要去除&
前缀
AbstractBeanFactory.java
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
转换 alias name
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
do {
resolvedName = (String)this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while(resolvedName != null);
return canonicalName;
}
转换 factoryBean name
// BeanFactoryUtils.java
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// BeanFactory.FACTORY_BEAN_PREFIX = "&"
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
转换逻辑还是比较简单清晰的。
FactoryBean 的使用
一般情况下, Spring 通过反射机制利用bean的 class 属性指定实现类来实例化 bean。在某些情况下,实例化 bean 过程比较复杂,如果按照传统的方式,则需要在 中提供大量的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring 为此提供了一个org.springframework.bean.factory.FactoryBean
的工厂类接口,用户可以实现该接口定制实例化bean 的逻辑。
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
// 返回由FactoryBean 创建的 bean实例,如果 isSingleton() 返回true,则该实例会放到Spring 容器中单实例缓存池中
@Nullable
T getObject() throws Exception;
// 返回由FactoryBean 创建的bean类型
@Nullable
Class<?> getObjectType();
// 返回由 FactoryBean 创建的 bean实例的作用域是singleton 还是 prototype
default boolean isSingleton() {
return true;
}
}
该接口定义的3个方法:
T getObject()
: 返回由FactoryBean
创建的 bean实例,如果isSingleton()
返回true,则该实例会放到Spring 容器中单实例缓存池中。getObjectType()
: 返回由FactoryBean
创建的bean类型。isSingleton()
: 返回由FactoryBean
创建的 bean实例的作用域是singleton
还是prototype
。
当配置文件中<bean>
的 class 属性配置的实现类是 FactoryBean
时,通过getBean()
方法返回的不是 FactoryBean
本身, 而是FactoryBean#getObject()
方法所返回的对象,相当于 FactoryBean#getObject()
代理了 getBean()
方法。
例如:
public class MyTestBeanFactoryBean implements FactoryBean<TestBeanFactoryBean> {
@Override
public TestBeanFactoryBean getObject() throws Exception {
TestBeanFactoryBean testBeanFactoryBean = new TestBeanFactoryBean();
testBeanFactoryBean.setId("1111");
testBeanFactoryBean.setName("hello");
return testBeanFactoryBean;
}
@Override
public Class<?> getObjectType() {
return TestBeanFactoryBean.class;
}
}
<?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.xsd">
<bean id="testFactoryBean" class="com.zh.sound.pojo.MyTestBeanFactoryBean"/>
</beans>
测试:
@Test
public void test1(){
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("spring-testFactoryBean.xml"));
Object testFactoryBean = xmlBeanFactory.getBean("testFactoryBean");
System.out.println(testFactoryBean.getClass());
}
// 输出结果为:class com.zh.sound.pojo.TestBeanFactoryBean
当调用 getBean("testFactoryBean")
时, Spring 通过反射机制发现 MyTestBeanFactoryBean 实现了 FactoryBean
的接口,这时Spring 容器就调用接口方法 MyTestBeanFactoryBean#getObject()
方法返回。如果希望获取 MyTestBeanFactoryBean的实例,则需要在使用 getBean(beanName) 方法时在 beanName 前显示的加上 &
前缀,例如 getBean("&testFactoryBean")
.
尝试从缓存中获取单例
// 尝试从缓冲中获取单例
Object sharedInstance = getSingleton(beanName);
单例在Spring 的同一个容器内只会被创建一次,后续在获取bean,就会直接从单例缓存中获取了。当然这里也只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从 singletonFactories
中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring 中创建bean的原则是不等bean 创建完成就会将创建 bean的 ObjectFactory 提早曝光加入到缓存中,一旦下一个bean 创建时候需要依赖上一个bean则直接使用 ObjectFactory
。
DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName) {
// 参数true 代表允许早期依赖
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 检查缓存中是否存在实例
Object singletonObject = 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) {
// 调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
// 记录在缓存中,earlySingletonObjects 和singletonFactories 互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
这里几个容器就是解决循环依赖的几个容器:
singletonObjects
: 用于保存 beanName 和创建 bean的实例之间的关系, beanName ->bean instance,注意,这里面存储的是已经创建完成的beansingletonFactories
: 用于保存 beanName 和创建bean的工厂之间的关系, beanName -> ObjectFactory. 注意:这里面保存的是创建bean的工厂,也就是对 bean分配完空间,给的内容地址earlySingletonObjects
:也是保存 beanName 和 创建bean 实例之间的关系,与 singletonObjects 的不同之处在于,当一个单例 bean被放到这里面后,那么当 bean还在创建过程中,就可以通过 getBean 方法获取到了,其目的是用来检测循环引用。registeredSingletons
: 用来保存当前所有已 创建成功的单例 bean名称列表.singletonCurrentlyInCreation
: 用来保存正在创建的单例名称队列
从 bean 的实例中获取对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
在 getBean 方法中, getObjectForBeanImstance
是个高频率使用的方法,无论是从缓存中获得bean
还是根据不同的scope
策略加载bean
。 总之,我们得到bean的实例后要做的第一步就是调用这个方法来检测一个正确性,其实就是用于检测当前bean 是否是 FactoryBean 类型的 bean, 如果是,那么需要调用该 bean 对应的 FactoryBean
实例中的 getObject()
作为返回值。
AbstractBeanFactory.java
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 判断给定的name 是否是 工厂的获取类型,也就是以 &开头的
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 如果当前bean 不是FactoryBean 类型,则抛出异常,否则直接返回 FactoryBean的实例
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 如果不是 FactoryBean 类型,直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 尝试从缓存中加载bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 到这里已经明确知道 beanInstance 一定是 FactoryBean 类型
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// containsBeanDefinition 检测 beanDefinitionMap 中也就是在所有已经加载的类中检测是否定义beanName
if (mbd == null && containsBeanDefinition(beanName)) {
// 将存储XML 配置文件的GernericBeanDefinition 转换为 RootBeanDefinition,
// 如果指定 BeanName 是子Bean的话同时会合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否用户定义的而不是应用程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
上面代码的工作流程:
- 判断name 的获取是否是 FactoryBean 类型,也就是 name是否包含
&
。 - 对 FactoryBean 正确性的验证。
- 对非 FactoryBean 不做任何处理。
- 对 bean 进行转换
- 将从 Factory 中解析bean的工作 委托给
getObjectFromFactoryBean
.
FactoryBeanRegistrySupport.java
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 如果是单例模式
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
//
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
// 调用 ObjectFactory 的后处理器
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
在这个代码中只做了两件事,
- 返回的bean 如果是单例的,那就必须要保证全局唯一,核心方法
doGetObjectFromFactoryBean
- 调用
postProcessObjectFromFactoryBean
后置处理器
在doGetObjectFromFactoryBean
方法中,看到了我们想要的方法 object = factory.getObject()
;
FactoryBeanRegistrySupport.java
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
// 权限验证
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 直接调用getObject()
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
上面就是 FactoryBean
的调用方法,如果bean 声明为 FactoryBean 类型,则当提取bean时 提取的并不是 FactoryBean, 而是FactoryBean 中对应的 getObject
方法返回的bean. 而 doGetObejctFromFactoryBean
正是实现这个功能的。
AbstractAutowireCapableBeanFactory.java
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
对于后处理器的使用,在Spring 获取bean的规则中有这样一条:尽可能保证所有bean 初始化后都会调用注册的BeanPostProcessor 的 postProcessAfterInitialization 方法进行处理。
获取单例
前面是从缓冲中获取单例的过程,那么如果缓冲中不存在已经加载的单例bean, 就需要从头开始 bean的加载过程,
在getBean方法中:
// 如果是单例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
spring 中使用了 getSingleton
的重载方法实现 bean的加载过程
DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 全局变量需要同步
synchronized (this.singletonObjects) {
// 首先检测对应的bean 是否已经加载过,因为 singleton 模式其实就是复用以创建的bean,所以这一步是必须的
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 创建前记录状态
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 初始化bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 加载完成后删除状态
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 加入缓存
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
上述代码中其实是使用了回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,而真正的获取单例bean 的方法其实并不是在此方法中实现的,实现逻辑是在 ObjectFactory 类型的实例 singletonFactory 中实现。而这些准备及处理操作包括如下内容。
- 检测缓存是否已经加载过。
- 若没有加载,则记录beanName 的正在加载状态
- 加载单例前记录加载状态
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
- 通过调用参数传入的ObjectFactory 的个体Object 方法实例化bean。
- 加载单例后的处理方法调用。
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
- 如果是第一次加载这个单例 bean,则存储到内存中。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
- 返回处理结果
虽然我们已经从外部了解了加载bean 的逻辑架构,但现在我们还并没有开始对bean 加载功能的探索,之前提到过,bean的加载逻辑其实是在传入的 ObjectFactory 类型的参数 singletonFactory 中定义的,我们反推参数的获取,得到如下代码:
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
ObjectFactory 的核心部分其实只是调用了 createBean 的方法,所以我们还需要到 createBean 方法中寻求真理
准备创建bean
我们不可能指望在一个函数中完成一个复杂的逻辑,而且跟踪了这么多的Spring 代码,发现一些规律:一个真正干活的函数其实都是以 do 开头的,比如 doGetObjectFromFactoryBean
; 而给我们错觉的函数,比如:getObjectFromFactoryBean
, 其实只是从全局角度去做些统筹的工作。这个规则对于createBean
也不例外,那么让我们看看在createBean
函数中做了哪些准备工作。
AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 锁定 class,根据设置的class 属性或者根据className 来解析Class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 验证以及准备覆盖的方法
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 给 BeanPostProcessors 一个机会来返回代理来替代真正的实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 真正工作的核心方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
从代码中我们可以总结出函数完成的具体步骤及功能。
- 根据设置的class属性或者根据className 来解析Class
- 对 override 属性进行标记及验证。
其实在Spring 中确实没有 override-method 这样的配置,但是在Spring 配置中是存在lookup-method
和replace-method
的,而这两个配置的加载其实就是将配置统一存放在BeanDefinition
中的methodOverrides
属性里,而这个函数的操作其实也就是针对这两个配置的。 - 应用初始化前的后处理器,解析指定bean 是否存在初始化前的短路操作。
- 创建bean
处理override属性
AbstractBeanDefinition.java
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exist and determine their overloaded status.
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
// 获取对应类中对应方法名的个数
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
// 标记MethodOverride 暂未被覆盖,避免参数类型检测的开销
mo.setOverloaded(false);
}
}
通过上面两个函数的代码可以发现,在spring 配置中存在lookup-mehtod
和 replace-method
两个配置功能,而这两个配置的加载其实就是将配置统一存放在BeanDefinition
中的 methodOverrides
属性里,这两个功能实现原理其实是在bean 实例化的时候如果检测到存在methodOverrides 属性,会动态的为当前bean 生成代理并使用对应的拦截器 为 bean 做增强处理。
但是,对于方法的匹配,如果一个类中存在若干个重载方法,那么,在函数调用及增强的时候还需要根据参数类型进行匹配,来最终确定当前调用的是那个函数。但是在这里,spring在准备方法覆盖的同时也判断了方法有没有被重载,可以省掉后面调用是的验证。
实例化的前置处理
在真正调用doCreateBean 方法之前还有一个操作,那就是调用Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
来对 beanDefinition
中属性做些前置处理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果前置处理返回值不为null, 则直接返回
if (bean != null) {
return bean;
}
当经过前置处理后的结果如果不为空,那么直接略过后续的 bean 的创建而直接返回结果。这一特性虽然很容易被忽略,但是却至关重要,我们熟知的 AOP 功能就是基于这里判断的。
AbstractAutowireCapableBeanFactory.java
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 如果没有被解析
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 前置处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 如果前置处理返回不为空,则调用后置处理
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
此方法中最吸引我们的无疑是两个方法 applyBeanPostProcessorsBeforeInstantiation
以及 applyBeanPostProcessorsAfterInstantiation
。两个方法实现的非常简单,无非是对后处理器中的所有 InstantiationAwareBeanPostProcessor
类型的后处理器进行 postProcessBeforeInstantiation
方法和BeanPostProcessor
的 postProcessAfterInitialization
方法的调用。
实例化前的后处理器应用
bean 的实例化前调用,也就是将 AbstractBeanDefinition
转换为 BeanWrapper
前的处理。给子类一个修改 BeanDefinition 的机会,也就是说当程序经过这个方法后,bean可能已经不是我们认为的bean 了,而是或许成为了一个经过代理的代理bean,可能是通过 cglib
生成的,也可能是通过其他技术生成的。我们只需要知道,在bean的实例化前会调用后处理器的方法进行处理。
AbstractAutowireCapableBeanFactory.java
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
实例化后的后处理器应用
Spring 中的规则是在bean初始化后尽可能保证将注册的后处理器的 postProcessAfterInitialization
方法应用到该 bean 中,因为如果返回的 bean 不为空,那么便不会再次经历普通 bean 的创建过程,所以只能在这里应用后处理器的 postProcessAfterInitialization
方法。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
循环依赖
什么是循环依赖
循环依赖就是循环引用,就是两个或多个bean 相互之间的持有对方,比如 TestA 引用了 TestB,TestB引用TestC, TestC 引用TestA, 则他们形成一个闭环。
Spring 如何解决循环依赖
Bean的循环依赖分为 构造器循环依赖
和 setter循环依赖
以及 prototype 范围的依赖处理
构造器循环依赖
表示通过构造器注入构成的循环依赖,此依赖时无法解决的,只能抛出BeanCurrentlyInCreationExcaption
异常表示循环依赖。
如在创建TestA 类时,构造器需要TestB 类,那就去创建TestB,在创建TestB类时又发现需要TestC 类,则又去创建TestC, 最终在创建TestC 时发现又需要TestA ,从而形成一个环,没有办法创建。
Spring 容器将每一个正在创建的bean 标识符放在一个 “当前创建bean池” 中,bean 标识符在创建过程中将一直保持在这个池中,因此如果在创建bean过程中发现自己已经在 “当前创建bean池” 里时,将抛出BeanCurrentlyInCreationException 异常表示循环依赖;而对于创建完毕的bean 将从 “当前创建bean池” 中清除掉。
setter循环依赖
表示通过setter注入方式构成的循环依赖。对于setter注入造成的依赖是通过Spring 容器暴露刚完成构造器注入但未完成其他步骤(如setter注入)的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使其他bean能引用到该bean,如以下代码:
AbstractAutowireCapableBeanFactory.java
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
具体步骤如下。
- Spring 容器创建单例 “testA” bean, 首先根据无参构造器创建bean, 并暴露一个
“ObjectFactory”
用于返回一个提前暴露一个创建中的bean, 并将 “testA” 标识符放到 “当前创建bean池”,然后进行setter注入 “testB”. - Spring 容器创建单例 “testB” bean, 首先根据无参构造器创建bean, 并暴露一个
“ObjectFactory”
用于返回一个提前暴露一个创建中的bean, 并将 “testB” 标识符放到 “当前创建bean池”,然后进行setter注入 “testC”. - Spring 容器创建单例 “testC” bean, 首先根据无参构造器创建bean, 并暴露一个
“ObjectFactory”
用于返回一个提前暴露一个创建中的bean, 并将 “testC” 标识符放到 “当前创建bean池”,然后进行setter注入 “testA”。进行注入 “testA” 时由于提前暴露了 “ObjectFacoty” 工厂,从而使用它返回提前暴露一个创建中的bean - 最后依赖注入 “testC” 和 “testB”, 完成setter注入
Spring 中的容器说明
DefaultSingletonBeanRegistry.java
singletonObjects
: 用于保存 beanName 和创建 bean的实例之间的关系, beanName ->bean instance,注意,这里面存储的是已经创建完成的beansingletonFactories
: 用于保存 beanName 和创建bean的工厂之间的关系, beanName -> ObjectFactory. 注意: 这里面保存的是创建bean的工厂,也就是对 bean分配完空间,给的内容地址, 也就是存储创建单例bean 时提前暴露的 ObjectFactory.earlySingletonObjects
:也是保存 beanName 和 创建bean 实例之间的关系,与 singletonObjects 的不同之处在于,当一个单例 bean被放到这里面后,那么当 bean还在创建过程中,就可以通过 getBean 方法获取到了,其目的是用来检测循环引用。registeredSingletons
: 用来保存当前所有已 创建成功的单例 bean名称列表.singletonCurrentlyInCreation
: 用来保存正在创建的单例名称队列
循环依赖流程图
prototype 范围的依赖处理
对于 “prototype
” 作用域 bean, Spring 容器无法完成依赖注入,因为Spring 容器不进行缓存 “prototype” 作用域的 bean, 因此无法提前暴露一个创建中的bean.
创建bean
当经历过 resolveBeforeInstantiation
方法后,程序有两个选择,如果创建了代理或者重写了 InstantiationAwareBeanPostProcessor
中的 postProcessBeforeInstantiation
方法并在该方法改变了 bean,则直接返回就可以了,否则需要进行常规bean的创建,而这常规bean的创建就是在doCreateBean
中完成的。
AbstractAutorireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 如果是单例,则从缓存中取值
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根据指定bean 使用对应的策略创建新的实例,如:工厂方法,构造函数自动注入,简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 应用 MergedBeanDefinitionPostProcessors
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 为避免后期循环依赖,可以在bean 初始化完成前将创建实例的ObjectFactory 加入工厂
addSingletonFactory(beanName,
// 其中我们熟知的AOP 就是在这里将 advice 动态织入bean中,若没有则直接返回bean不做任何处理
() -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始依赖bean
populateBean(beanName, mbd, instanceWrapper);
// 调用欧冠初始化方法,比如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// earlySingletonReference 只有在检测有循环依赖的情况才会不为空
if (earlySingletonReference != null) {
// 如果exposedObject 没有在初始化方法中被改变,也就是没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 检测依赖
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
/**
* 因为bean 创建后所依赖的bean 一定是已经创建的,
* actualDependentBeans 不为空则表示当前bean创建后其依赖的bean 却没有全部创建完,也就是说存在循环依赖
*/
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// 根据 scope 注册 bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
doCreateBean的 流程:
- 如果是单例则需要首先清除缓存
- 实例化bean, 将
BeanDefinition
转换为BeanWrapper
.
转换是一个复杂的过程,但是我们可以尝试概括大致的功能,如下所示。- 如果存在工厂方法则使用工厂方法初始化
- 一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化。
- 如果即不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行bean 的实例化。
MergedBeanDefinitionPostProcessor
的应用。 bean 合并后的处理,Autowired
注解正是通过此方法实现诸如类型的预解析。- 依赖处理。
- 属性填充。将所有属性填充至bean的实例中。
- 循环依赖检查。Spring 中解决循环依赖只对单例有效,而对于prototype 的bean,Spring 没有好的解决办法,唯一要做的就是抛出异常。在这个步骤里面会检测已经加载的 bean 是否已经出现了依赖循环,并判断是否需要抛出异常。
- 注册
DisposableBean
, 如果配置了destory-method
,这里需要注册以便于在销毁时候调用 - 完成创建并返回
创建 bean的实例
深入分析创建bean 的每一个步骤,从第一步 createBeanInstance
开始。
AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 解析class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果工厂方法不为空则使用工厂方法初始化策略
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 一个类由多个构造函数,每个构造函数都有不同的参数,所以调用前需要先
// 根据参数锁定构造函数活对应的工厂方法
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已经解析过则使用解析好的构造函数方法不需要再次锁定
if (resolved) {
if (autowireNecessary) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}
// 需要根据参数解析构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
虽然代码非常复杂,但是 createBeanInstance
方法中还是可以很清晰的看到实例化的逻辑。
- 如果
RootBeanDefinition
中存在factormMethodName
属性,或者说在配置文件中配置了factory-method
, 那么Spring 会尝试使用instantiateUsingFactoryMethod(beanName, mbdn args)
方法根据RootBeanDefinition
中的配置生产 bean的实例。 - 解析构造函数并进行构造函数的实例化。因为一个bean 对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring 在根据参数及类型去判断最终会使用那个构造函数进行实例化。但是判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从RootBeanDefinition 中属性
resolvedConstyuctorOrFactoryMethod
缓存的值去取,否则需要再次 解析,并将解析的结果添加至RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 中。
autowireConstructor 构造函数自动注入
对于实例的创建 Spring 中分成了两种情况,一种是通用的实例化,李毅中是带有参数的实例化。带有参数的实例化过程相当复杂,因为存在着不确定行,所以在判断对应参数上做了大量工作。
ConstructorResolver.java
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// explicitArgs 是通过getBean 方法传入的构造函数参数
// 如果getBean 方法调用的时候指定方法参数那么直接使用
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
// 如果在getBean 方法时没有指定则尝试从配置文件中解析
Object[] argsToResolve = null;
// 尝试从缓存中获取
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// 从缓存中取
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 配置的构造函数参数
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
// 如果缓存中存在,则进行解析参数类型
if (argsToResolve != null) {
// 解析参数类型,如给定方法的构造函数A(int, int)则通过此方法后就会把配置中的
// ("1", "1") 转换为 (1,1)
// 缓存中的值可能时原始值也可能时最终值
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
// 如果没有被缓存,则取RootBeanDefinition 的所有构造函数
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
// 如果构造函数就一个,并且没有入参
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// instantiate 实例化 bean
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// 需要解析构造函数
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// 提取配置文件中的配置的构造函数参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 用于承载解析后的构造函数参数的值
resolvedValues = new ConstructorArgumentValues();
// 能解析到的参数个数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
int parameterCount = candidate.getParameterCount();
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
if (resolvedValues != null) {
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
if (parameterCount != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
// instantiate 构建实例,并将构建好的实例加入 BeanWrapper 中
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
逻辑很复杂,函数代码量很大,总览一个整个函数,其实现的功能考虑了一下几个方面。
- 构造函数参数的确定: 根据explicitArgs 参数判断 或者缓存中获取,或者配置文件中获取
- 构造函数的确定
- 根据确定的构造函数转换对应的参数类型
- 构造函数不确定性的验证
- 根据实例化策略以及得到的构造函数及构造函数参数实例化 Bean
instantiateBean (无参构造)
经历了带有参数的构造函数的实例构造,再来看不带参数的构造函数的实例化过程会非常简单。
AbstractAutowireCapableBeanFactory.java
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
发现没有什么实质性的逻辑,带有参数的实例构造中,Spring 把经历都放在了构造函数以及参数的匹配上,所以没有参数的实例化过程就是直接调用实例化策略就可以了。
实例化策略
实例化过程中反复提到过实例化策略,其实,经过前面的分析,我们已经得到了足以实例化的所有相关信息,完全可以使用最简单的反射方法直接反射来构造实例对象,但是Spring 却并没有这么做。
SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 如果有需要覆盖或者动态替换的方法则当然需要使用cglib 进行动态代理,因为可以在创建代理的同时
// 将动态方法织入类中,如果没有需要动态改变的方法,为了方便直接使用反射就可以了
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 使用cglib 进行代理
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
CglibSubclassingInstantiationStrategy.java
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass);
}
else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
首先判断如果 beanDefinition.hasMethodOverrides()
为空也就是用户没有使用replace
或者 lookup
的配置方法,那么直接使用反射的方式,简单快捷,但是如果使用了这两个方法,在直接使用反射的方式创建实例就不行了,因为需要将这两个配置提供的功能切入进去,所以就必须要使用动态代理的方式将包含两个特性所对应的逻辑拦截增强器设置进去,这样才可以保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。
记录创建bean 的 ObjectFactory
在doCreateBean 函数中有这样一段代码
// 是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 为避免后期循环依赖,可以在bean 初始化完成前将创建实例的ObjectFactory 加入工厂
addSingletonFactory(beanName,
// 其中我们熟知的AOP 就是在这里将 advice 动态织入bean中,若没有则直接返回bean不做任何处理
() -> getEarlyBeanReference(beanName, mbd, bean));
}
这段代码并不复杂:
earlySingletonExposure
: 从字段的意思理解就是提早曝光的单例,我们看一下影响它的值mbd.isSingleton()
:表示此 RootBeanDefinition 代表的是否是单例this.allowCircularReferences
:表示 是否允许循环依赖isSingletonCurrentlylnCreation(beanName)
: 表示该bean 是否在创建中。在Spring 中,会有个专门的属性默认为DefaultSingletonBeanRegistry
的singletonCurrentInCreation
来记录bean的加载状态,在bean 开始创建前会将 beanName 记录在属性中,在bean 创建结束后会将 beanName 从属性中移除。不同的scope 的记录位置并不一样,以singleton
为例,在singleton 下记录属性的函数是在DefaultSingletonBeanRegistry
类的public Object getSingleton(String beanName, ObjectFactory singletonFactory)
函数的beforeSingletonCreation(beanName)
和afterSingletonCreation(beanName)
中,在这两端函数中分别this.singletonsCurrentlyInCreation.add(beanName)
与this.singletonsCurrentlyInCreation.remove(beanName)
来进行状态的记录与移除。
所以earlySingletonExposure
是否是单例,是否允许循环依赖,是否对应的bean正在创建的条件的综合。当着3个条件都满足时会执行 addSingletonFactory
操作,那么加入SingletonFactory 的作用是什么,有时在什么时候调用那?
以简单的AB循环依赖为例,类A 中含有属性类B, 而类B 中又会含有属性类A, 那么初始化beanA 的过程如下:
上图展示了创建 beanA的流程,途中我们看到,在创建A 的时候首先会记录类A 所对应的 beanName, 并将beanA 的创建工厂加入缓存中,而在对A的属性填充也就是条用populate 方法时候又会再一次的对B 进行递归创建。同样的,因为在B 中同样存在 A 属性,因此在实例化B的 populate 方法中又会再次的初始化B, 也就是图形的最后,调用getBean(A)。 其中 getEarlyBeanReference
的代码如下:
AbstractAutowireCapableBeanFactory.java
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
在 getEarlyBeanReference
函数中并没有太多的逻辑处理,或者说除了后处理器的调用外没有别的处理工作,根据以上分析,基本上可以理清 Spring 处理循环依赖的解决办法,在B 中创建依赖 A 时通过 ObjectFactory 提供的实例化方法来中断A 中的属性填充,使B 中持有的A 仅仅时刚刚初始化并没有填充任何属性的A, 而这初始化A 的步骤还是在最开始创建A的时候进行的,但是因为 A 与 B 中的A所表示的属性地址是一样的,所以在 A中创建好的属性填充自然可以通过B 中的 A 获取,这样就解决了循环依赖的问题。
属性注入
在了解循环依赖的时候,我们反复提到了 populateBean
这个函数,也了解了这个函数的主要功能就是属性填充,那么究竟是如何实现填充的呐?
AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// 没有可填充的属性
return;
}
}
// 给 InstantiationAwareBeanPostProcessors 最后一次机会在属性设置前来改变bean
// 如: 可以用来支持属性注入的类型
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 返回值为是否继续填充bean
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 后处理器已经初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 对所有需要依赖检查的属性进行后处理
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 检查依赖,对应depends-on 属性,3.0已经启用此属性
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
// 将属性应用到 bean 中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
在 populateBean 函数中提供了这样的处理流程。
InstantiationAwareBeanPostProcessor
处理器的postProcessAfterInstantiation
函数的应用,此函数可以控制程序是否继续进行属性填充。- 根据注入类型(
byName/byType
),提取依赖的bean, 并统一存入PropertyValues
中。 - 应用
InstantiationAwareBeanPostProcessor
处理器的postProcessPropertyValues
方法,对属性获取完毕填充前对属性的再次处理,典型应用就是RequiredAnnotationBeanPostProcessor
类中对属性的验证。 - 将所有
PropertyValues
中的属性填充至BeanWrapper
中。
在上面的步骤中有几个地方比较有意思,分别是 依赖注入(autowireByName
/ autowireByType
) 以及属性填充,那么,接下来进一步分析这几个功能的实现细节。
autowireByName
按照名称自动注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 寻找 bw 中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 递归初始化相关的 bean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
// 注册依赖
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
autowireByType
autowireByType 与 autowireByName 对于我们理解与使用来说复杂程度都很相似,但是其实现功能的复杂度却完全不一样。autowireByType 是按照 类型自动注入
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 寻找 bw 中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
if (Object.class != pd.getPropertyType()) {
// 探测指定属性的set 方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 解析指定 beanName 的属性所匹配的至,并把解析到的属性名称存储在
// autowiredBeanNames 中,当属性存在多个封装 bean时,如:
// @Autowired
// private List<A> aList;
// 将会找到所有匹配 A 类型的bean 并将其注入
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
// 注册依赖
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
实现根据名称自动匹配的第一步就是寻找 bw 中需要依赖注入的属性,同样对于根据类型自动匹配的实现来讲,第一步也是寻找 bw 中需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的 bean, 其中最复杂的就是寻找类型匹配的bean. 其中最复杂的就是寻找类型匹配的 bean。 同时, Spring 中提供了对集合的类型注入的支持,如使用注解的方式:
@Autowired
private List<Test> tests;
Spring 将会把所有与 Test匹配的类型找出来并注入到 tests 属性中,增势由于这一因素,所以在 autowireByType 函数中,新建了局部遍历 autowiredBeanNames, 用于存储所有依赖的bean.
初始化 Bean
在 bean 配置时 bean 中有一个 init-method
的属性,这个属性的作用是在 bean 实例化前调用 init-method 指定的方法来根据用户业务进行相应的实例化。这个方法的执行位置就是, Spring 中程序已经执行过 bean 的实例化,并且进行了属性的填充,而就在这是将会调用用户设定的初始化方法。
AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 对特殊的 bean 处理:Aware, BeanClassLoaderAware, BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 应用后处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 激活用户自定义的 init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 后处理应用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
虽然说此函数的主要目的是进行客户设定的初始化方法的调用,但是除此之外还有些其他必要的工作。
-
激活 Aware 方法
在分析其原理之前,我们先了解一下Aware 的使用。Spring 中提供一些 Aware 相关接口,比如 BeanFactoryAware, ApplicationContextAware, ResourceLoaderAware, ServletContextAware 的bean在初始化后,Spring 容器将会注入 BeanFactory 的实例,而实现 ApplicationContextAware 的 bean, 在bean 被初始化后,将会被注入 ApplicationContext 的实例等。我们首先通过实例方法来了解一下 Aware的使用。-
定义普通 bean
public class Hello { public void sayHello(){ System.out.println("hello"); } }
-
定义BeanFactoryAware 类型的bean.
public class Test implements BeanFactoryAware { private BeanFactory beanFactory; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } public void testAware(){ // 通过 bean id 从 beanFactory 获取实例 Hello hello = (Hello) beanFactory.getBean("hello"); hello.sayHello(); } }
-
定义 spring-aware.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.xsd"> <bean id="hello" class="com.zh.sound.pojo.Hello" /> <bean id="test" class="com.zh.sound.pojo.Test" /> </beans>
-
测试
@Test public void test1(){ XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("spring-testFactoryBean.xml")); Object testFactoryBean = xmlBeanFactory.getBean("&testFactoryBean"); System.out.println(testFactoryBean.getClass()); } // 输出结果为 "hello"
按照上面的方法我们可以获取到 Spring 中 BeanFactory, 并且可以根据 BeanFactory 获取所有 bean, 以及进行相关设置。当然还有其他 Aware的使用方法都大同小异,看一个 Spring的实现方式:
private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
可以看到实现非常简单,就是遇到不同的 Aware, 对不同的Aware 传递不同的参数。
-
-
处理器的应用
BeanPostProcessor
相信大家都不陌生,这是Spring 中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或扩展 Spring, 而除了BeanPostProcessor
外还有很多其他的PostProcessor
, 当然大部分都是以此为基础,继承自 BeanPostProcessor. BeanPostProcessor 的使用位置就是这里,在调用客户自定义初始化方法前以及调用自定义初始化方法后分别会调用 BeanPostProcessor 的postProcessBeforeInitialization
和postProcessAfterInitialization
方法,根据用户自己的业务需求进行响应的处理。
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
- 激活自定义的init 方法
用户定制的初始化方法除了我们熟知的使用配置 init-mehtod
外,还可以使自定义的 bean 实现 InitializingBean
接口,并在 afterPropertiesSet
中实现自己的初始化业务逻辑。
init-method
与 afterPropertiesSet
都是在初始化 bean 时执行,执行顺序是 afterPropertiesSet
限制性,而 init-method
后执行。
在 invokeInitMethods
方法中就实现了这两个步骤的初始化方法调用。
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 首先会检查是否是 InitializaingBean, 如果是的话需要调用 afterPropertiesSet 方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 属性初始化后的处理
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 调用自定义初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
注册 DisposableBean
Spring 中不但提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口,对于销毁方法的扩展,除了我们熟知的配置属性 destory-method 方法外,用户还可以注册后处理器 DestructionAwareBeanPostProcessor
来统一处理 bean的销毁方法。
AbstractBeanFactory.java
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// 单例模式下注册需要销毁的bean, 此方法中会处理实现 DisposableBean 的bean
// 并且对所有的 bean 使用 DestructionAwareBeanPostProcessors 处理
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// 自定义scope 的处理
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}