springIOC源码接口分析(八):AutowireCapableBeanFactory
参考博文: https://blog.csdn.net/f641385712/article/details/88651128
一 接口规范
从宏观上看,AutowireCapableBeanFactory提供了如下能力:
1 为已经实例化的对象装配属性,这些属性对象都是Spring管理的;
2 实例化一个Bean,并自动装配,这些被装配的属性对象都是Spring管理的,但是实例化的Bean可以不被Spring管理(这点特别重要)。所以这个接口提供功能就是自动装配bean相关的
(自动装配的原对象可以不在Spring的IOC容器里,但是需要被依赖注入的成员,就必须是Spring容器管辖的Bean)
此接口主要是针对框架之外,没有向Spring托管Bean的应用。通过暴露此功能,Spring框架之外的程序,也能具有自动装配的能力(此接口赋予它的)。
可以使用这个接口集成其它框架。捆绑并填充(注入)并不由Spring管理生命周期并已存在的实例.像集成WebWork的Actions 和Tapestry Page就很实用
一般应用开发者不会使用这个接口,所以像ApplicationContext这样的外观实现类不会实现这个接口,
但是提供了getAutowireCapableBeanFactory()方法允许你拿这个工具去做你需要的事。
接口定义:
public interface AutowireCapableBeanFactory01 extends BeanFactory {
/**
* 表明工厂没有自动装配的Bean
*/
int AUTOWIRE_NO = 0;
/**
* 表明根据名称自动装配
*/
int AUTOWIRE_BY_NAME = 1;
/**
* 表明根据类型自动装配
*/
int AUTOWIRE_BY_TYPE = 2;
/**
* 表明根据构造方法快速装配
*/
int AUTOWIRE_CONSTRUCTOR = 3;
@Deprecated
// 表明通过Bean的class的内部来自动装配 Spring3.0被弃用。
int AUTOWIRE_AUTODETECT = 4;
String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
/**
* 创建一个指定class的实例
*/
<T> T createBean(Class<T> beanClass) throws BeansException;
/**
* 通过调用给定Bean的after-instantiation及post-processing接口,对bean进行配置
*/
void autowireBean(Object existingBean) throws BeansException;
/**
* 自动装配属性,填充属性值,使用诸如setBeanName,setBeanFactory这样的工厂回调填充属性,最好还要调用post processor
*/
Object configureBean(Object existingBean, String beanName) throws BeansException;
/**
* 创建一个指定class的实例,通过参数可以指定其自动装配模式(by-name or by-type).
*/
Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
/**
* 通过指定的自动装配策略来初始化一个Bean
*/
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
/**
* 通过指定的自动装配方式来对给定的Bean进行自动装配
*/
void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
throws BeansException;
/**
* 将参数中指定了那么的Bean,注入给定实例当中
*/
void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
/**
* 初始化参数中指定的Bean,调用任何其注册的回调函数如setBeanName、setBeanFactory等。
*/
Object initializeBean(Object existingBean, String beanName) throws BeansException;
/**
* 调用参数中指定Bean的postProcessBeforeInitialization方法
*/
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException;
/**
* 调用参数中指定Bean的postProcessAfterInitialization方法
*/
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException;
/**
* 销毁参数中指定的Bean,同时调用此Bean上的DisposableBean和DestructionAwareBeanPostProcessors方法
*/
void destroyBean(Object existingBean);
/**
* 查找唯一符合指定类的实例,如果有,则返回实例的名字和实例本身
* 底层依赖于:BeanFactory中的getBean(Class)方法
*/
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
/**
* 解析出在Factory中与指定Bean有指定依赖关系的Bean(@Autowired依赖注入的核心方法)
*/
Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
}
二 实际应用
准备一个外部类,即不被spring容器管理:
public class Person {
//不使用@Autowired
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
spring管理的User bean进行实例化,这里以spring-bean.xml为例:

利用AutowireCapableBeanFactory创建Bean:
public class BeanTest{
@Test
public void beanTest(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");
//ApplicationContext没有实现接口,但是可以通过方法直接获取使用
AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
// autowireCapableBeanFactory创建Bean实例,执行多次就创建多个
Person person = (Person) autowireCapableBeanFactory.createBean(Person.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
//没有@Autowired注解也直接给注入了
System.out.println("获取自动注入的属性:"+person.getUser());
//异常: No qualifying bean of type 'com.hou.spring.Person' available
Person bean = applicationContext.getBean(Person.class);//没有交给spring容器管理
System.out.println(bean);
}
}
执行结果:

不使用接口测试:

三 源码分析
主要从createBean方法进行分析:
这个接口调用的方法是在AbstractAutowireCapableBeanFactory抽象类中实现的:
@Override
public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
//这里设置为原型,而不是单例,所以调用多次会生成多个对象
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
return createBean(beanClass.getName(), bd, null);
}
然后就是return里面调用的createBean方法,这个是AbstractAutowireCapableBeanFactory类的父类AbstractBeanFactory定义的抽象方法:
AbstractAutowireCapableBeanFactory类中实现了这个抽象方法,这个方法很单纯:创建一个实例,然后初始化他(给属性们赋值),然后return出去即可:
@Override
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; // Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
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 产生了一个代理对象,就不需要我去创建了,就不继续往下走了(AOP都走这里)
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 {
//本类的一个protected方法,专门用于处理创建Bean的过程(包括属性赋值之类的)
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);
}
}
再看本类的doCreateBean方法,主要有三个核心步骤三个步骤:createBeanInstance、populateBean、initializeBean:
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实例,返回一个BeanWrapper,它也是本类的一个protected方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
} // 处理循环引用,现在若我们Bean不在容器里,肯定是不存在循环引用的(但是我依赖的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;
}
} // Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} Object exposedObject = bean;
try {
//// 给Bean实例的各个属性进行赋值
populateBean(beanName, mbd, instanceWrapper);
//初始化Bean 执行一些初始化方法init @PostContruct方法等等
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
其他具体细节以后其他博文专门记录笔记
springIOC源码接口分析(八):AutowireCapableBeanFactory的更多相关文章
- springIOC源码接口分析(三):ApplicationContext
一 新增方法 主要都是获取容器基本信息的一些接口,比如获取名称,id和启动时间戳,获取AutowireCapableBeanFactory等接口 二 继承接口 ApplicationContext继承 ...
- springIOC源码接口分析(九):Environment
先贴一下接口继承关系图,spring容器启动的时候会初始化环境,所以此接口相关接口非常有必要进行了解: 一 PropertyResolver接口 Environment继承了该接口,PropertyR ...
- springIOC源码接口分析(十一):ConfigurableApplicationContext
一 实现接口 关系图: ConfigurableApplicationContext接口实现了三个接口,ApplicationContext, Lifecycle, Closeable, Applic ...
- springIOC源码接口分析(七):ApplicationEventPublisher
一 定义方法 此接口主要是封装事件发布功能的接口,定义了两个方法: /** * 通知应用所有已注册且匹配的监听器此ApplicationEvent */ default void publishEve ...
- springIOC源码接口分析(六):ResourceLoader
参考博客: https://www.cnblogs.com/jixp/articles/10702486.html 一 定义方法 Spring提供了ResourceLoader接口用于实现不同的Res ...
- springIOC源码接口分析(五):ListableBeanFactory
一 继承关系 该接口是对BeanFactory的扩展,允许预加载bean定义的BeanFactory可以实现此接口 其目的在于使实现它的BeanFactory能够枚举所有的Bean 该接口不支持分层结 ...
- springIOC源码接口分析(四):MessageSource
一 定义方法 MessageSource接口用于支持信息的国际化和包含参数的信息的替换 这个接口定义了三个方法: public interface MessageSource { /** * 解析co ...
- springIOC源码接口分析(二):ConfigurableBeanFactory
一 继承功能 1 SingletonBeanRegistry接口 此接口是针对Spring中的单例Bean设计的.提供了统一访问单例Bean的功能,类中定义了以下方法: 2 HierarchicalB ...
- springIOC源码接口分析(一):BeanFactory
一 应用场景 BeanFactory接口定义了IOC容器的最基本功能,提供了容器应该具有的功能规范,所有的容器都应该实现这个接口 BeanFactory设计了getBean方法用来获取容器中的Bean ...
随机推荐
- 快速部署 Spring PetClinic 到函数计算平台
简介 首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute):函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传.函数计算准 ...
- 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树
正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...
- 洛谷$P$3746 [六省联考2017]组合数问题 $dp$+矩乘+组合数学
正解:$dp$+矩乘+组合数学 解题报告: 传送门! 首先不难发现这个什么鬼无穷就是个纸老虎趴,,,最多在$\binom{n\cdot k+r}{n\cdot k}$的时候就已经是0了后面显然不用做下 ...
- PrototypePattern(原型模式)-----Java/.Net
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式.
- 1059 C语言竞赛 (20 分)C语言
C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛.既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽: 0.冠军将赢得一份"神秘大奖"(比如很巨大的一本学生研究论文集--). 1 ...
- 【一起学源码-微服务】Ribbon 源码三:Ribbon与Eureka整合原理分析
前言 前情回顾 上一篇讲了Ribbon的初始化过程,从LoadBalancerAutoConfiguration 到RibbonAutoConfiguration 再到RibbonClientConf ...
- 12.pyecharts详细使用教程
官方数据教程: 柱状图-Bar //导入柱状图-Bar from pyecharts import Bar //设置行名 columns = ["Jan", "Feb&q ...
- 类加载器在Tomcat中的应用
之前有文章已经介绍过了JVM中的类加载机制,JVM中通过类加载加载class文件,通过双亲委派模型完成分层加载.实际上类加载机制并不仅仅是在JVM中得以运用,通过影响字节码生成和类加载器目前已经有了许 ...
- 二次排序LincodeNo.846
846.Multi-keyword Sort 题目要求在已经排序好的序列上进行二次排序 那么改变一下比较方法即可 bool cmp(vector<int> a,vector<int& ...
- Scala实践5
一.Scala的层级 1.1类层级 Scala中,Any是所其他类的超类,在底端定义了一些有趣的类NULL和Nothing,是所有其他类的子类. 根类Any有两个子类:AnyVal和AnyRef.其中 ...