1 回顾:使用springIOC的流程
- 使用spring的时候,可以通过两种方式:xml配置和注解驱动的方式;
- 最终通过ApplicationContext从ioc容器中就可以通过getBean的方式(通过BeanFactory的getBean的)生产 Bean
getBean其实是生产Bean,并非是获取Bean,而是根据我们的配置给我们生产Bean,只是spring做了一层缓存,看起来像是获取获取Bean
这里就有一个问题xml和注解驱动是通过不同的方式(ClassPathXmlApplicationContext,AnnotationConfigApplicationContext)来获取Bean;虽然使用的类不同,但是无论我们哪种方式配置肯定是要读取成一个统一的方式啊,交给BeanFactory来生产BeanBean(解耦)
2 springIOC的整体脉络
2.1 Bean定义( BeanDefinition)
无论是注解驱动还是xml最终都会将这些配置,读取成一个个的Bean定义( BeanDefinition);
org.springframework.beans.factory.config.BeanDefinition
是spring的一个顶层接口
可以看一下他的一个抽象实现org.springframework.beans.factory.support.AbstractBeanDefinition
// 部分代码展示
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// 当前bean的class类型
@Nullable
private volatile Object beanClass;
private boolean primary = false;
@Nullable
private String scope = SCOPE_DEFAULT;
@Nullable
private String initMethodName;
@Nullable
private String destroyMethodName;
@Nullable
private Boolean lazyInit;
}
发现这抽线实现里面定义了许多我们在配置Bean的时候可以配置的选项(scope,initinitMethod,primary,是不是懒加载。。。)
spring会把这些bean定义最终存到一个Map里面
既然有个这个统一的Bean定义,那么就需要知道如何将这些Bean定义收集起来了?
2.2 注册Bean定义(BeanDefinitionRegistry)
如何将我们的Bean定义收集起来了?
就通过这个接口org.springframework.beans.factory.support.BeanDefinitionRegistry
其中就声明了这么一个方法,注册BeanDefinition:
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
这个接口还有其他的方法声明,比如removeBeanDefinition(删除Bean定义);
AnnotationConfigApplicationContext就实现了这个接口
就通过这个registerBeanDefinition将一个个的Bean定义最终注册(收集到)一个Map中
这个接口只是注册Bean定义,显然还需要一个组件将我们的xml或者配置类读取为Bean定义;
不仅仅还有读取,我们通常还会配置扫描的包,只会扫描这个包下带有@Component这种注解的Bean才会最终被Spring管理
2.3 BeanDefinitionReader和ClassPathBeanDefinitionScanner
这两个组件就是负责读取和扫描
2.3 生产Bean的大致流程
Bean定义已经处理完成之后,当我们调用getBean的时候就会生产Bean,就会发生一下大概的几个流程
-
实例化,可以通过反射(比如xml配置的时候就是通过反射)或者new(配置类中往往就是通过new)
-
接下来就是填充属性,比如通过@Autowired; @Value等注解注入的属性
-
如果配置了init方法就会去调用我们配置的初始化方法
-
如果配置了销毁方法,当Bean销毁的时候就会调用对应的销毁方法
-
最终会将这个Bean放到一个Map中(单例池),一级缓存
3 spring中的扩展点
上面介绍了大致的流程,这些流程中还内置了很多扩展点,spring的生态为何如此牛逼,就是因为这些扩展点的存在,让其他框架都可以与之整合
3.1 Bean定义的核心扩展点
3.1.1 修改Bean定义:BeanFactoryPostProcessor
package org.springframework.beans.factory.config;
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
/**
All bean definitions will have been loaded, but no beans:
说明这个方法执行的时候所有的Bean definition已经加载,但是没有生产Bean
**/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
eg:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
* 形参就是bean工厂
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 根据beanName获取某个bean定义
BeanDefinition user = beanFactory.getBeanDefinition("user");
System.out.println(user.getBeanClassName());
// 修改这个bean定义中的BeanClassName
user.setBeanClassName("java.lang.String");
}
}
3.1.2 注册Bean定义:BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
形参就是BeanDefinitionRegistry,就可以通过这个BeanDefinitionRegistry注册BeanDefinition;
mybatis和spring的整合就是通过这个去实现的
扫描Bean和配置类都是通过BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor实现的
3.2 Bean的生命周期中的扩展点
在实例化,填充属性的时候都有系列的BeanPostProcessor,来扩展我们的Bean
一共会调用9此BeanPostProcessor
这里就先不多介绍
4 BeanFactory和ApplicationContext的区别
- ApplicationContext中的getBean也是调用BeanFactory的getBean
- BeanFactory就是个工厂,根据Bean定义生产Bean
- ApplicationContext是面向用户的,不仅仅要提供Bean和调用工厂去生成Bean,还要提供一系列的其他功能(如果国际化,加载Bean定义等等)
- ApplicationContext是依赖BeanFactory,没有BeanFactory就无法生成Bean
// ApplicationContext
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
}