内容概要:
- BeanFactory 实现的特点
- ApplicationContext 的常见实现和用法
- 内嵌容器、注册DispatcherServlet
BeanDefinition
通过控制反转来创建bean
BeanDefinition
包括(class、Scope 单例/多例、初始化方法、销毁方法)
BeanDefinitionBuilder
创建bean的定义,设置Bean相关信息@Configuration
组件,并不会自动将里面@Bean标示的其他Bean自动注册到BeanFactory,需要一些后处理器来补充这些Bean的定义BeanFactoryPostProcessor
BeanFactoryPostProcessor
的主要功能: 补充一些Bean的定义到BeanFactory, 例如 @Bean 注解BeanFactoryPostProcessor
(Bean的定义),才会将@Bean等信息的Bean的定义注册到BeanFactoryBeanPostProcessor
BeanPostProcessor
的主要功能: 针对bean的生命周期的各个阶段提供扩展,例如 @Autowired @Resurece…@Slf4j
public class MainController {
public static void main(String[] args) {
// 1)创建BeanFactory,新创建的BeanFactory里面什么也没有
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2)创建Bean的定义(class,scope,初始化,销毁),并向BeanFactory中注册bean的定义
//BeanFactory是根据bean的定义`BeanDefinition`,通过控制反转来创建bean,想要BeanFactory容器添加某个Bean,就需要BeanFactory中添加Bean的定义(此时并不会主动初始化bean对象)
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope(BeanDefinition.SCOPE_SINGLETON).getBeanDefinition();
beanFactory.registerBeanDefinition("config", beanDefinition);
/*
// 2.1)向beanFactory注册一个@Configuration组件,并不会自动将里面@Bean标示的其他Bean自动注册到BeanFactory
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
// 输出只有config
System.out.println(beanDefinitionName);
}
System.out.println("2.1>>>>>>>>>>>>>>>>>");
*/
// 3)向BeanFactory中添加一些常用的后处理器(Bean的定义)
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// 3.1)打印后处理器Bean的定义
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
// 输出多了5个后处理器
System.out.println(beanDefinitionName + "--->" + beanFactory.getBeanDefinition(beanDefinitionName));
}
System.out.println("3.1>>>>>>>>>>>>>>>>>");
// 4)BeanFactory后处理器的主要功能: 补充一些Bean的定义到BeanFactory, 例如 @Bean..
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor-> {
System.out.println(beanFactoryPostProcessor);
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
System.out.println("4>>>>>>>>>>>>>>>>>");
/*
// 4.1)BeanFactory后处理器,将Bean1和Bean2的Bean的定义添加到BeanFactory
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
// 输出多了 bean1 bean2
System.out.println(beanDefinitionName);
}
System.out.println("4.1>>>>>>>>>>>>>>>>>");
*/
/*
// 4.2)BeanFactory并不会主动初始化Bean对象,通过BeanFactory获取Bean对象时,才会初始化
// 获取Bean1对象,此时Bean1对象中通过@Autowired注入的Bean2对象并没有初始化
System.out.println("bean1.getBean2():" + beanFactory.getBean(Bean1.class).getBean2()); // 打印bean1 create, 输出bean2为null
System.out.println("4.2>>>>>>>>>>>>>>>>>");
*/
// 5)Bean后处理器的主要功能: 针对bean的生命周期的各个阶段提供扩展,例如 @Autowired @Resurece..
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanPostProcessor -> {
System.out.println(beanPostProcessor);
beanFactory.addBeanPostProcessor(beanPostProcessor);
});
System.out.println("5>>>>>>>>>>>>>>>>>");
// beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor); // 使用方法引用代替lambda表达式
// 5.1)Bean后处理器,将Bean1对象中的Bean2对象初始化注入进去
System.out.println("bean1.getBean2():" + beanFactory.getBean(Bean1.class).getBean2());// 打印bean1 create, bean2 create,
System.out.println("5.2>>>>>>>>>>>>>>>>>");
// 6) 在使用Bean之前,先初始化单例对象
beanFactory.preInstantiateSingletons();
}
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
@Slf4j
static class Bean1 {
@Autowired
private Bean2 bean2;
public Bean1() {
log.info("Bean1() create");
}
public Bean2 getBean2() {
return bean2;
}
}
@Slf4j
static class Bean2 {
public Bean2() {
log.info("Bean2() create");
}
}
}
@Autowired
注入规则:先根据class类型匹配,当class类型存在多个,再根据成员变量的名字匹配bean的名字
@Resource
注入规则:先根据class类型匹配,当class类型存在多个,如果注解中的变量name存在,则根据name匹配bean的名字,若不存在,则根据成员变量的名字匹配bean的名字
@Autowired
优先级低于 @Resource
,当注入bean时同时加上了这两个注解,优先匹配 @Resource
查看Bean后处理器优先级源码 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
方法
AutowiredAnnotationBeanPostProcessor
后处理器作用:解析@Autowired
注解,将注入的bean定义加入到BeanFactoryCommonAnnotationBeanPostProcessor
后处理器作用:解析@Resource
注解,将注入的bean定义加入到BeanFactory// AutowiredAnnotationBeanPostProcessor 成员变量
private int order = Ordered.LOWEST_PRECEDENCE - 2;
// CommonAnnotationBeanPostProcessor 构造器
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
// ...
}
示例:
interface Inter {}
class Bean1 implements Inter {}
class Bean2 implements Inter {}
@Configuration
class Config {
@Bean
public Inter bean3() {
return new Bean3();
}
@Bean
public Inter bean4() {
return new Bean4();
}
}
class TestComponent {
@Autowired
private Inter inter; // 找不到bean, 注入失败 (Could not autowire. There is more than one bean of 'Inter' type. Beans: bean1、bean2)
@Autowired
private Inter bean3; // 注入bean3, 根据成员变量的名字匹配
@Resource
private Inter bean3; // 注入bean3, 根据成员变量的名字匹配
@Resource(name = "bean4")
private Inter bean3; // 注入bean4, 根据name匹配
@Autowired
@Resource(name = "bean4")
private Inter bean3; // 注入bean4, @Autowired 优先级低于 @Resource
}
总结:
${}
、#{}
ClassPathXmlApplicationContext
: 基于类路径(classpath)下读取 Spring 的 xml 配置文件创建ApplicationContextprivate static void testClassPathXmlApplicationContext() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
// 注入了两个Bean, bean5 和 bean6
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
// bean6中的bean5也自动注入成功
System.out.println(context.getBean(Bean6.class).getBean5());
}
<bean id="bean5" class="com.xxx.xxx.entity.Bean5" />
<bean id="bean6" class="com.xxx.xxx.entity.Bean6">
<property name="bean5" ref="bean5" />
bean>
static class Bean5 {
// 必须要有空构造方法
public Bean5() {
}
}
static class Bean6 {
// 必须要有空构造方法
public Bean6() {
}
private Bean5 bean5;
public Bean5 getBean5() {
return bean5;
}
public void setBean5(Bean5 bean5) {
this.bean5 = bean5;
}
}
FileSystemXmlApplicationContext
: 基于磁盘路径下读取 Spring 的 xml 配置文件创建ApplicationContext
private static void testFileSystemXmlApplicationContext() {
// 支持绝对路径,也支持传入从项目根目录开始的相对路径
// FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("/Users/wangli/idea-workspace/study-spring/src/main/resources/bean01.xml");
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/bean01.xml");
// 注入了两个Bean, bean5 和 bean6
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
// bean6中的bean5也自动注入成功
System.out.println(context.getBean(Bean6.class).getBean5());
}
private static void testXmlApplicationContext() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 新创建的BeanFactory 什么也没有
System.out.println("before read..");
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
// 初始化XmlBeanDefinitionReader, 设置将读取到的BeanDefinition注册到beanFactory
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// 设置读取xml文件资源
reader.loadBeanDefinitions(new ClassPathResource("bean01.xml"));
// reader.loadBeanDefinitions(new FileSystemResource("src/main/resources/bean01.xml"));
// 读取到两个bean, bean5 和 bean6
System.out.println("after read..");
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
<context:annotion-config />
AnnotationConfigApplicationContext
: 基于 Java 配置类来创建ApplicationContext
private static void testAnnotationConfigApplicationContext() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
// 读取到了8个bean, 除了 bean5 和 bean6 外,还有 Config 和 5个BeanFactory注册的后处理器
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
// bean6中的bean5也自动注入成功
System.out.println(context.getBean(Bean6.class).getBean5());
}
@Configuration
static class Config {
@Bean
public Bean5 bean5() {
return new Bean5();
}
@Bean
public Bean6 bean6(Bean5 bean5) {
Bean6 bean6 = new Bean6();
bean6.setBean5(bean5);
return bean6;
}
}
AnnotationConfigServletWebServerApplicationContext
: 基于 java 配置类来创建,用于 web 环境ServletWebServerFactory
: 提供ServletWebServer的工厂类,用于创建ServletWebServer
DispatcherServlet
: 前控制器,作用是将请求分发到对应到控制器DispatcherServletRegistrationBean
: 用于注册DispatcherServlet到web容器Controller
控制器,web请求入口点,由DispatcherServlet分发指定请求路径为的请求到这个控制器进行处理private static void testAnnotationInitApplicationContext() {
AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
// 读取到了10个bean, 5个BeanFactory注册的后处理器 + WebConfig + servletWebServerFactory + dispatcherServlet + registrationBean + /hi
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
@Configuration
static class WebConfig {
/**
* ServletWebServer:内嵌了一个基于servlet技术的web容器,常见的内嵌容器:Tomcat内嵌容器
* ServletWebServerFactory:提供ServletWebServer的工厂类,用于创建ServletWebServer
* @return
*/
@Bean
public ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
/**
* DispatcherServlet:前控制器,作用是将请求分发到对应到控制器
* @return
*/
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
/**
* DispatcherServletRegistrationBean:用于注册DispatcherServlet到web容器
* @param dispatcherServlet
* @return
*/
@Bean
public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
}
/**
* Controller: 控制器web请求入口点,由DispatcherServlet分发请求路径为 "/hi" 的请求到这个控制器进行处理
* @return
*/
@Bean("/hi")
public Controller controller1() {
return new Controller() {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.getWriter().write("hi");
return null;
}
};
}
}