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 ...
随机推荐
- CodeTypeDeclaration,CodeMemberProperty动态生成代码
由于是CodeDom些列,所以先介绍几个CodeDom表达式: :CodeConditionStatement:判断语句即是if(condition){} else{},看最全的那个构造函数: pub ...
- CPP 设计模式学习
源地址 https://www.ev0l.art/index.php/archives/20/ 备忘录模式 在一个类内部记录另一个类的快照状态的模式.可以再合适的时候跳回复用 设计备忘录的三大步骤: ...
- 选题Scrum立会报告+燃尽图 02
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8680 组长:杨天宇 组员:魏新,罗杨美慧,王歆瑶,徐丽君 组名:组长 第 ...
- 【题解】P4137 Rmq Problem(莫队)
[题解]P4137 Rmq Problem(莫队) 其实这道题根本就不用离散化! 因为显然有\(mex\)值是\(\le 2\times 10^5\)的,所以对于大于\(2\times 10^5\)的 ...
- $Poj2228$/洛谷$SP283\ Naptime$ 环形$DP$
Luogu 一定要记得初始化为-inf!!! Description 在某个星球上,一天由N小时构成.我们称0-1点为第一个小时,1-2点为第二个小时,以此类推.在第i个小时睡觉能恢复Ui点体力.在这 ...
- java poi ppt 接口的基本操作
依赖 在 pom.xml中增加以下依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId& ...
- 集合排序Comparable和Comparator有什么区别?
Comparable和Comparator兄弟俩长得是真像.但是,需要注意下,使用中它们还是有不少区别的.下面,就一探究竟吧. 一.Comparator 做过集合排序的童鞋应该知道,可以使用Colle ...
- Java网络编程——UDP聊天程序
UDP简介 UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据报.在OSI模型中,UDP位于第四层--传输层,处于IP协议额上一层.UDP有不提供数据报分组.组装以及不能对数据报排序 ...
- 1038 统计同成绩学生 (20 分)C语言
题目描述 本题要求读入N名学生的成绩,将获得某一给定分数的学生人数输出. 输入描述: 输入在第1行给出不超过105的正整数N,即学生总人数.随后1行给出N名学生的百分制整数成绩,中间以空格分隔.最后1 ...
- 1045 快速排序 (25 分)C语言
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边. 给定划分后的 N 个互不相同的正整数的排列,请问 ...