Spring
是一个开源的设计层面框架,解决了业务逻辑层和其他各层的松耦合问题,将面向接口的编程思想贯穿整个系统应用,同时它也是
Java工作中
必备技能之一…
<!– more –>
前言
在 Spring解密 – XML解析 与 Bean注册 中,讲了 Bean的解析
,本章将详细讲解Spring中Bean的加载过程
,相比解析
而言,加载稍微复杂一点.
入口
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Person person = context.getBean("person", Person.class);
System.out.println(person.toString());
}
}
重点分析 context.getBean();
解密
在分析 Bean
的加载过程前,我们看看 BeanFactory
的由来,以及 getBean
所属的类是谁。磨刀不误砍柴工
BeanFactory 的由来
1.查看getBean()
的源码,此处的 getBeanFactory()
是怎么来的?
public class AbstractApplicationContext{
@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
// getBeanFactory() 是怎么来的?我们接着看
return getBeanFactory().getBean(name, requiredType);
}
}
2.应用程序的上下文
在 new ClassPathXmlApplicationContext("bean.xml");
中,跳转到重载的构造方法中,我们会发现如下代码
public class ClassPathXmlApplicationContext {
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
// 解析 bean.xml 文件
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
}
它的目的是将普通路径解析为 类(classpath)
路径资源名称。多个配置文件的情况下,后加载的 Bean
会覆盖先前定义好的 Bean
,这样做的目的是为了通过额外的XML文件来特意重写某个 Bean
。这里我们可以看到调用了一个 refresh()
,它的作用是什么呢?
3.初始化
刷新容器
public class AbstractApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新上下文
prepareRefresh();
// 通知子类,刷新内部 BeanFactory(创建 BeanFactory 的入口)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
}
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 跟踪该方法
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
}
初次加载完 bean.xml
后,肯定会进入到 refresh()
方法中,这个时候会做容器初始化的工作,也就是 标签解析、Bean加载
等等工作,由于本章重点介绍 Bean加载
,所以只贴了少量代码(看官莫急)
创建
DefaultListableBeanFactory
public class AbstractRefreshableApplicationContext {
@Override
protected final void refreshBeanFactory() throws BeansException {
// 判断是否存在
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 然后赋值给 beanFactory 变量
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
// 提取 BeanFactory
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
}
从上面的代码块中,我们可以看到 如果已经存在 beanFactory,将销毁旧的实例,然后在创建新的 DefaultListableBeanFactory
,最后 getBeanFactory()
就可以正常使用了。
Bean 加载
整个 Bean
的装载过程中,重点围绕 AbstractBeanFactory
,只要把它搞定剩下的就轻松了
public abstract class AbstractBeanFactory {
@Override
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 {
// 别名转换
final String beanName = transformedBeanName(name);
Object bean;
// 检查缓存中是否存在 该 Bean 的单例(Bean默认的Scope = singleton)
// 比如容器初始化的时候或者其他地方调用过getBean,已经完成了初始化
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 返回实例,FactoryBean 的情况下,并不是直接返回实例本身而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 存在循环依赖则报错
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 判断工厂中是否含有当前 Bean 的定义
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果没有,查询父工厂
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 执行带有 args 参数的 getBean 方法
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 如果没有参数,执行标准的 getBean 方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) { // 如果不是做类型检查,则需要标记此 Bean 正在创建之中
markBeanAsCreated(beanName);
}
try {
// 将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,如果BeanName是子Bean的话会合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 获取依赖的 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);
getBean(dep);
}
}
// 终于开始创建 Bean 实例了,如果是单例的,那么会创建一个单例的匿名工厂,
// 如果是原型模式的,则不需要创建单例的工厂的,其他的如 request、session 作用域的,则根据自身的需要
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);
}
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, () -> {
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;
}
}
// 类型检查,如果不能进行类型转换,则抛出异常
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.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;
}
}
整个代码块的内容还是不少的,接下来我们一步一步的分析。
转换 BeanName
final String beanName = transformedBeanName(name);
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
去除 FactoryBean
的修饰符,最终取指定 alias
所表示的 beanName
。因为有可能获取到以 & 开头的 FactoryBean
,所以要进行转化(关于 BeanFactory
和 FactoryBean
后面会进行区分)
加载单例
检查缓存中是否存在 该 Bean
的单例(Bean默认的Scope = singleton)
,如容器初始化的时候或者其他地方已经调用过 getBean()
完成了初始化
Object sharedInstance = getSingleton(beanName);
缓存加载 Bean
默认在装载 Bean
的时候会先去检查 singletonObjects
是否存在,如果存在直接提取缓存的。
public class DefaultSingletonBeanRegistry {
/** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 保存 BeanName 和创建 bean 实例的工厂之间的关系 bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
/** 与 singletonObjects 不同的是当一个单例 bean 被放到里面后,那么在 bean 在创建过程中,就可以通过 getBean 方法获取到,可以用来检测循环引用。 **/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** 保存当前所有已注册的 bean */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
@Nullable
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) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 存入到缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
}
构建实例(无缓存情况)
缓存中没有,那就当场构建一个 bean
出来,可以看到 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
有两个参数,其中的 ObjectFactory
是怎么来的呢? 接着往下看
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 记录加载状态,,以便对循环依赖进行检测
beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
// 移除加载状态
afterSingletonCreation(beanName);
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
构建
ObjectFactory
此处与其说是构建 ObjectFactory
,不如说是在创建一个单例 Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 对 JDK8 lambda 表达式熟悉的小伙伴就不会陌生了
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 划重点了
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
创建 Bean
public class AbstractAutowireCapableBeanFactory {
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 首先判断需要创建的bean是否可以被实例化,这个类是否可以通过类装载器来载入。
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 返回代理来替代真正的实例(如果 Bean 配置了 PostProcessor,那么这里返回的是一个代理)
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.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException ex) {
// A previously detected exception with proper bean creation context already...
throw ex;
}
catch (ImplicitlyAppearedSingletonException ex) {
// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
}
在创建 Bean
之前,Spring
还做了不少工作。
- 判断创建的
bean
是否可以被实例化,这个类是否可以通过ClassLoader
来载入,根据设置的class
属性或根据className
来解析class
。 - 对覆盖进行标记并验证,在
Spring
配置中存在lookup-mothod
和replace-method
的,这两个配置的加载时将配置统一存放在BeanDefinition
中的methodOverrides
属性里,这个方法的操作也是针对于这两个配置的; - 应用初始化前的后处理器,最后创建
bean
。在createBean()
方法里执行完resolveBeforeInstantiation
方法后,如果创建了代理且不为空的话就直接返回,否则需要进行常规bean
的创建,这个创建过程是在doCreateBean
中完成的
初始化 Bean
上面 createBean
交给了 doCreateBean
来创建 bean
(上面还有一个重要的方法getObjectForBeanInstance,在后面分析)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 实例化 Bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根据指定 bean 使用相应策略创建实例(正确情况会调用无参构造函数)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取实例化好的 Bean(Person person = new Person()),此处还未进行赋值
final Object bean = instanceWrapper.getWrappedInstance();
// 获得实例化好的 class
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 记录创建 Bean 的 ObjectFactory,初始化前调用 post-processors,可以让我们在 bean 实例化之前做一些定制操作
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
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.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化bean实例。
Object exposedObject = bean;
try {
// 在这个方法里面初始化对象,配置 xml 中的各种属性
populateBean(beanName, mbd, instanceWrapper);
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);
if (earlySingletonReference != null) {
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);
}
}
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.");
}
}
}
}
// 用于销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
上面源码完成的操作可以概括为以下几点
-
RootBeanDefinition
是不是单例,如果是单例先移除缓存 - 实例化
bean
,将RootBeanDefinition
转换为BeanWrapper
- 使用
MergedBeanDefinitionPostProcessor
,Autowired注解
就是通过此方法实现类型的预解析; - 解决循环依赖问题
- 在
populateBean()
中填充属性,配置在XML
中的各种属性 - 注册到
DisposableBean
中 - 完成创建并返回
Bean
的实例
接下来我们看下 Spring
是如何创建 bean
实例的。跟踪 createBeanInstance()
方法
创建Bean实例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 获取 beanClass , 要先确保 Bean 是正确的,已经解析到当前节点了
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() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 没有特殊处理的情况下,只需使用无参数的构造函数。
return instantiateBean(beanName, mbd);
}
可以看出如果在 RootBeanDefinition
中存在 factoryMethodName
属性,或者说配置文件中配置了 factory-method
,那么 Spring
会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args)
方法根据 RootBeanDefinition
中的配置生成bean实例。然后再解析构造方法并进行实例化,Spring
会根据参数及类型判断使用哪个构造方法进行实例化。判断调用哪个构造方法的过程会采用缓存机制,如果已经解析过则不需要重复解析而是从 RootBeanDefinition
中的属性 resolvedConstructorOrFactoryMethod
缓存的值去取,否则需再次解析。
populateBean 属性注入
这块代码比较多,有兴趣请自行跟进,就不贴出来了
在 populateBean
方法的中的主要处理流程:
-
InstantiationAwareBeanPostProcessor
处理器的postProcessAfterInstantiation
方法控制程序是否继续填充属性; - 根据注入类型提取依赖的
bean
,并存入PropertyValues
中; -
InstantiationAwareBeanPostProcessor
处理器的postProcessPropertyValues
方法对属性在填充前再次处理(主要还是验证属性); - 将所有
PropertyValues
中的属性填充到BeanWrapper
中;
initializeBean 初始化Bean
学过 Spring
的都知道 bean
配置时有一个 init-method
属性,这个属性的作用是在 bean
实例化前调用 init-method
指定的方法进行需要的操作,现在就进入这个方法了;Spring
执行过 bean
的实例化,并且进行属性填充后,就会调用用户设定的初始化方法。
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处理
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用配置的 init-method
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;
}
最后加载完 Bean
并执行完初始化操作后,一个 bean
的加载基本就结束了。
增强的 Bean
通过上面的描述,我们已经知道了一个的 Bean
是如何初始化的,已经具备普通 Bean
的功能。但是 Spring
还提供了一种增强的 Bean(FactoryBean)
,具备 factory
能力的 Bean
,这个能力主要在 getObjectForBeanInstance
得到。
public class AbstractBeanFactory {
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果想要获取 FactoryBean 本身,那么 beanInstance 必须是 FactoryBean 的实例
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 如果 instance 不是 FactoryBean 实例,或者想要获取的就是 FactoryBean 实例,那么直接返回就好
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
// 获取缓存的实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 缓存中没有对象,那么从头准备 bean defition 实例化一个
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 在这里面获得最终的FactoryBean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
}
关于 BeanFactory
和 FactoryBean
的区别:
- BeanFactory: 容器的基本接口,是一个工厂,用来生产
Bean
- FactoryBean: 是一个特殊的
Bean
,可以当作工厂使用的Bean
循环依赖
上面有简单提到过 循环依赖(只有在单例情况下才会尝试解决循环依赖)。 无法解决就只能抛出 BeanCurrentlyInCreationException
异常
构造器循环依赖
无法解决,只能抛出 BeanCurrentlyInCreationException
异常
<bean id="A" class="com.battcn.A">
<constructor-arg index="0" ref="B" />
</bean>
<bean id="B" class="com.battcn.B">
<constructor-arg index="0" ref="C" />
</bean>
<bean id="C" class="com.battcn.C">
<constructor-arg index="0" ref="A" />
</bean>
setter 循环依赖
Spring
容器提前暴露了刚好完成的构造器注入,但未完成其他步骤 (如 setter 注入
的 bean
)。只能解决单例作用域的 bean
循环依赖。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
prototype 范围的依赖处理
Spring
容器无法完成依赖注入,因为 Spring
容器不会缓存 prototype
作用域的 bean
,因此无法提前暴露一个创建中的 bean
。
<bean id="A" class="com.battcn.A" scope="prototype">
<property name="B" ref="B" />
</bean>
<bean id="B" class="com.battcn.B" scope="prototype">
<property name="C" ref="C" />
</bean>
<bean id="C" class="com.battcn.C" scope="prototype">
<property name="A" ref="A" />
</bean>
总结
熬过几个无人知晓的秋冬春夏,撑过去一切都会顺着你想要的方向走…
说点什么
全文代码:https://gitee.com/battcn/battcn-spring-source/tree/master/Chapter4
- 个人QQ:1837307557
- battcn开源群(适合新手):391619659
微信公众号:battcn
(欢迎调戏)