Spring源码底层讲解
一.容器接口
1.1.BeanFactory功能
1.什么是BeanFactory
- 他是ApplicationContent 的父接口
- 它才是Spring的核心容器,主要的ApplicationContext实现都【组合】了它的功能
2.类图:3.BeanFactory功能
- 表面上只有getBean
- 实际上控制反转,基本的依赖注入,直至Bean的生命周期的各种功能,都由它的实现类提供
1.2.ApplicationContext的扩展功能
1.类图:
2.拓展的功能
- 国际化
ConfigurableApplicationContext context = SpringApplication.run(DoucaiWebApplication.class, args);
System.out.println(context.getMessage("hi",null, Locale.CHINA));
System.out.println(context.getMessage("hi",null, Locale.ENGLISH));
System.out.println(context.getMessage("hi",null, Locale.JAPANESE));
运行结果:
- 获取资源
ConfigurableApplicationContext context = SpringApplication.run(DoucaiWebApplication.class, args);
Resource[] resource = content.getResources("classpath*:META/spring.factories");
for (Resource resource1 : resource) {
System.out.println(resource);
}
运行结果:
- 获取环境信息
ConfigurableApplicationContext context = SpringApplication.run(DoucaiWebApplication.class, args);
System.out.println(context.getEnvironment().getProperty("java_home"));
运行结果:
- 发送事件
/**
* 1.需要创建事件对象
* 2.创建监听器对象 :监听到了就执行任务
*/
context.publishEvent(new UserRegisteredEvent(context));
二.容器实现
2.1.BeanFactory实现的特点
public class TestBeanFactory {
/**
*
* a.beanFactory不会做的事
* 1.不会主动调用BeanFactory 后处理器
* 2.不会主动添加 Bean 后处理器
* 3.不会主动初始化单例
* 4.不会解析beanFactory 还不会解析 ${}与#{}
* b.bean 后处理器会有排序的逻辑
*/
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(class,scope,初始化,销毁)
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
//把beanDefinition放入beanFactory中
beanFactory.registerBeanDefinition("config",beanDefinition);
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println("============================================================");
//给BeanFactory添加后处理器 用于解析 一些注解
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// beanFactory后处理器主要功能,补充一些bean的定义
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
// Bean后处理器,针对bean的生命周期的各个阶段提供扩展,例如@Autowired @Resource
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
// 就可以获取到Bean1中的Bean2了
System.out.println(beanFactory.getBean(Bean1.class).getBean2());
// 预先将Bean工厂中的单利对象先创建出来
beanFactory.preInstantiateSingletons();
}
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
static class Bean1 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean1() {
System.out.println("构造Bean1");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2() {
System.out.println("构造Bean2");
}
}
}
2.2.ApplicationContext的常见实现实现和用法
//1.较为经典的容器 基于classpath下xml格式的配置文件来创建
private static void testClassPathXmlApplicationContext() {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("b01.xml");
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println(context.getBean(Bean2.class).getBean1());
}
//2.基于磁盘路径下xml格式的配置文件来创建
private static void testFileSystemXmlApplicationContext() {
FileSystemXmlApplicationContext context =
new FileSystemXmlApplicationContext("src\\main\\resources\\b01.xml");
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println(context.getBean(Bean2.class).getBean1());
}
//3.较为经典的容器,基于java 配置类来创建
private static void testAnnotationConfigApplicationContext() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
System.out.println(context.getBean(Bean2.class).getBean1());
}
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2(Bean1 bean1) {
Bean2 bean2 = new Bean2();
bean2.setBean1(bean1);
return bean2;
}
return new Bean2();
}
}
//4.较为经典的容器,基于java 配置类来创建,用于 web 环境
private static void testAnnotationConfigServletWebServerApplicationContext() {
AnnotationConfigServletWebServerApplicationContext context =
new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
}
@Configuration
static class WebConfig{
@Bean
public static ServletWebServerFactory serverFactory(){
return new TomcatServletWebServerFactory();
}
@Bean
public static DispatcherServlet dispatcherServlet(){
return new DispatcherServlet();
}
@Bean
public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet){
return new DispatcherServletRegistrationBean(dispatcherServlet,"/");
}
@Bean("/hello")
public Controller controller1( ){
return (request, response) -> {
response.getWriter().print("hello");
return null;
};
}
}
问:ApplicationContext是如何读取到xml中的bean信息的呢?
答:通过XmlBeanDefinitionReader(代码如下)
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
System.out.println("读取之前...");
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println("读取之后...");
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.LoadBeanDefinitions(new ClassPathResource("b01.xml"));
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
运行结果:
三.Bean的生命周期
3.1 Spring bean 生命周期各个阶段
3.2模版方法设计模式
通过模版方法设计模式,可以在不改变getBean()方法的前提下拓展getBean()的功能
如下代码只是一个简单示例:给代码增加@Autowired和@Resource等操作
public class Demo01 {
public static void main(String[] args) {
MyBeanFactory myBeanFactory = new MyBeanFactory();
myBeanFactory.addBeanPostProcesser(bean -> {System.out.println("@Autowired操作");});
myBeanFactory.addBeanPostProcesser(bean -> {System.out.println("@Resource操作");});
myBeanFactory.getBean();
}
static class MyBeanFactory{
private List<BeanPostProcesser> list = new ArrayList<>();
public Object getBean(){
Object bean = new Object();
System.out.println("构造"+bean);
System.out.println("依赖注入"+bean);
for (BeanPostProcesser beanPostProcesser : list) {
beanPostProcesser.inject(bean);
}
System.out.println("初始化"+bean);
return bean;
}
public void addBeanPostProcesser(BeanPostProcesser beanPostProcesser){
list.add(beanPostProcesser);
}
}
static interface BeanPostProcesser{
void inject(Object bean);
}
}
四.Bean后处理器
4.1Bean后处理器作用
为Bean生命周期各个阶段提供扩展
4.2常见的后处理器
一:常见后处理器
- AutowiredAnnotationBeanPostProcessor 可以处理@Autwired @Value 这些注解进行增强
- CommonAnnotationBeanPostProcessor 可以处理@Resource @PostConstruct @PreDestroy 这些注解进行增强
- ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory()) 可以处理@ConfigurationProperties 这些注解进行增强
二:@Autowired Bean后处理器
DigInautowired.class
public class DigInautowired {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("bean2",new Bean2());
beanFactory.registerSingleton("bean1",new Bean1());
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 1.查找哪些属性,方法加了@Autowired,这称之为InjectionMetadata
AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
processor.setBeanFactory(beanFactory);
Bean1 bean1 = new Bean1();
System.out.println(bean1);
// 该方法就是执行依赖注入 @Autowired @Value
processor.postProcessProperties(null,bean1,"bean1");
System.out.println(bean1);
}
Bean1.class
public class Bean1 {
private Bean2 bean2;
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
@Autowired
public void setBean2(Bean2 bean2){
log.debug("@Autowired 生效1:{}",bean2);
this.bean2 = bean2;
}
@Autowired
public void setHome(@Value("${JAVA_HOME}") String home){
log.debug("@Autowired 生效2: {}",home);
}
}
Bean2.class
public class Bean2 {
}
如下截图中的findAutowiringMetadata方法就是寻找对象中的有@Autowired标注的方法和属性,可以从截图中看见
它注入了 bean1中锁包含的对象