spring源码
IOC
BeanFactory和ApplicationContext接口联系
BeanFactory是ApplicationContext的父接口,是spring的核心组成接口。ApplicationContext对BeanFactory进行了扩展,类图展示如下

beanFactory是ApplicationContext的一个成员变量,所以我们可以看出,ApplicationContext对象主要是对BeanFactory进行扩展

BeanFactory容器里面的管理单例对象,都存放在这个变量里面

BeanFactory初探
BeanFactory的接口定义如下

- 从表面上来看,仅仅只是定义了一些getBean方法
- 但是其实现类
DefaultListableBeanFactory实现了控制反转,依赖注入已经bean的生命周期

ApplicationContext接口的扩展功能

- MessageSource接口
定义了国际化的功能

- ResoucePatternResolver接口
定义了对资源读取

- EnvironmentCapable接口
定义了对配置变量的存储信息

- ApplicationEvenrPublisher接口
消息发布与订阅相关功能,主要运用的是观察者模式

总结
BeanFactory是ApplicationContext的父接口,是spring的核心组成接口。
但是ApplicationContext并不只是简简单单的父子接口关系,而是组合关系。
ApplicationContext对BeanFactory进行了一系列的功能扩展
练习:分别使用AOP和消息订阅与发布来实现用户注册的短信发送功能
AOP实现短信发送功能
1. 首先在UserService接口中定义注册功能
2. 在UserService的实现中,实现接口定义的功能
3. 编写AOP功能,在AOP中实现短信发送功能
4. 测试功能代码
- UserService接口
public interface UserService {
void register(User user);
}
- 编写UserService的实现类
@Service
public class UserServiceImpl implements UserService {
@Override
public void register(User user) {
System.out.println("查询user是否存在,若不存在便可注册");
System.out.println("用户注册");
}
}
- 通过AOP编写短信发送功能
@Aspect
@Component
public class RegisterAdvice {
@Around("execution(* com.xuanxie.impl.*.*(..))") // 我放在impl包下,可以自己做修改
public Object sendMessage(ProceedingJoinPoint pjp){
System.out.println("准备执行注册功能");
Object ret;
try {
ret = pjp.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
System.out.println("已完成注册服务,准备发送短信");
return ret;
}
}
- 编写测试代码
@SpringBootTest
class SpringIocApplicationTests {
@Autowired
private UserService userService;
@Test
void contextLoads() {
userService.register(new User());
}
}
消息订阅与发布实现短信发送功能
1. 首先在UserService接口中定义注册功能
2. 自定义事件RegisterEvent
3. 在UserService的实现中,实现接口定义的功能,同时发布消息
4. 定义监听类,在监听类中实现邮箱发送功能
5. 测试功能代码
- 首先在UserService接口中定义注册功能
public interface UserService {
void register(User user);
}
- 自定义事件RegisterEvent
public class RegisterEvent extends ApplicationEvent {
public RegisterEvent(Object source) {
super(source);
}
}
- 在UserService的实现中,实现接口定义的功能,同时发布消息
@Service
public class UserServiceListenerImpl implements UserService, ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void register(User user) {
System.out.println("用户注册成功");
applicationEventPublisher.publishEvent(new RegisterEvent("register"));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
- 定义事件监听器,在事件监听器中发送邮件
@Component
public class RegisterListener {
@EventListener
public void registerListener(RegisterEvent event){
System.out.println("发送邮件给用户");
}
}
- 测试代码
@SpringBootTest
class SpringIocApplicationTests {
@Autowired
private UserService userService;
@Test
void contextLoads() {
userService.register(new User());
}
}
容器的实现
BeanFactory的实现
DefaultListableBeanFactory
在BeanFactory的实现类里面,最重要是DefaultListableBeanFactory。
1. 创建DefaultListableBeanFactory工厂。
2. 创建AbstractBeanDefinition 这里面说明一些bean的定义。
3. 把BeanFactory的后处理器注册到BeanFactory,为了之后方便的拿到BeanFactory的后处理器。
4. 通过调用BeanFactory后处理器的方法,把@bean等注解进行解析。如名字所说 它仅仅指挥处理BeanFactory相关的部分,也就是可以处理bean的定义相关,但是不能对依赖注入处理,例如:@Autowired,@Resource等等。(bean的定义包括:class,scope,初始化等等)
5. 通过把Bean后处理器注册到BeanFactory工厂当中,这样便可处理@Autowired,@Resource
6. 通过以上过程便可以创建bean对象并且有依赖注入的功能,但是此时对于单例bean的创建是在其调用的时候才创建而不是在工厂创建时创建,所以需要手动调用方法来实现单例bean的创建
- 个人感觉,每一个后处理器都是对BeanFactory的一个扩展,BeanFactory的后处理器是扩展了bean定义的功能,例如:可以通过@Bean来创建Bean对象。Bean的后处理器是扩展了bean创建的功能,例如:通过@Autowired注解实现依赖注入。
public class TestBeanFactory {
public static void main(String[] args) {
// 创建BeanFactory的实现类
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// Bean的定义(class,scope,初始化。。。)
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config", beanDefinition);
// 此时只会输出一个config,因为现在beanFactory并没有解析@Bean注解
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println("name = " + name);
}
System.out.println("--------------------------");
// 给BeanFactory的后处理器,补充一些bean的定义 此时只是后处理器只是存在于BeanFactory当中,并没有与bean的创建产生联系
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// 此时的输出会多出一些常用的后处理器,但是bean1和bean2并不会创建
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println("name = " + name);
}
System.out.println("--------------------------");
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class)
.values()
.forEach(beanFactoryPostProcessor -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));
// 此时bean1和bean2也会输出,但是依赖注入功能没有实现,从bean1中并不会获得bean2
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println("name = " + name);
}
System.out.println("--------------------------");
// Bean后处理器,针对bean的生命周期各个阶段提供扩展,例如@Autowired @Resource ...
beanFactory.getBeansOfType(BeanPostProcessor.class)
.values()
// 通过这一步可以bean的创建与bean后处理器产生联系
.forEach(beanFactory::addBeanPostProcessor); // ==>.forEach(beanPostProcessor -> beanFactory.addBeanPostProcessor(beanPostProcessor));
// 此时我们可以发现单例的bean创也建是在使用的时候再创建而不是在工厂创建的时候创建
// System.out.println("--------------------------");
// System.out.println(beanFactory.getBean("bean1"));
// 为了让单例bean不是在使用的时候创建,我们需要使用 beanFactory.preInstantiateSingletons();来创建单例bean对象
beanFactory.preInstantiateSingletons();
System.out.println("--------------------------");
System.out.println(beanFactory.getBean("bean1"));
/*
beanFactory不会做的事情
1. 不会主动调用BeanFactory后处理器
2. 不会主动调用Bean后处理器
3. 不会主动创建单例对象
4. 不会解析#{}, ${}
*/
}
@Configuration
static class Config{
@Bean
public Bean1 bean1(){
return new Bean1();
}
@Bean
public Bean2 bean2(){
return new Bean2();
}
}
static class Bean1{
@Autowired
private Bean2 bean2;
public Bean1(){
System.out.println("Bean1.Bean1");
}
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2{
public Bean2(){
System.out.println("Bean2.Bean2");
}
}
}
ApplicationContext的实现
1. ClassPathXmlApplicationContext和FileSystemXmlApplicationContext都是通过读取xml来获取BeanDefinition,之后更具BeanFactory来创建Bean
- 具体过程
1. 创建BeanFactory
2. 创建xmlBeanDefinitionReader,构造函数的参数是解析xml的BeanDefinition放置位置
3. 传入带解析的xml文件(可以选择ClassPathResource解析也可以选择FileSystemResource解析)
4. 通过这种方式,并不会注入BeanFactory的后处理器,除非在xml配置文件中添加<context:annotation-driven/>
1.ClassPathXmlApplicationContext
ClassPathXmlApplicationContext 当我们初学的时候,都是学习该类去实现spring。现在我们再来回顾一下简单使用
public class TestApplicationContext {
public static void main(String[] args) {
// 与FileSystemXmlApplicationContext的最大区别就是路径不同,这里是从类路径读取文件,FileSystemXmlApplicationContext是从磁盘路径读取文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("b01.xml");
Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
System.out.println("------------------------");
System.out.println(bean1.getBean2());
}
}
<!-- spring配置文件-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean1" class="com.xuanxie.spring_ioc.TestApplicationContext.Bean1">
<property name="bean2" ref="bean2"/>
</bean>
<bean id="bean2" class="com.xuanxie.spring_ioc.TestApplicationContext.Bean2"/>
</beans>
2.FileSystemXmlApplicationContext
FileSystemXmlApplicationContext和FileSystemXmlApplicationContext很类似,我们先来看看它的用法
// java文件
public class TestApplicationContext {
public static void main(String[] args) {
// 与ClassPathXmlApplicationContext的最大区别就是路径不同,这里是从磁盘读取文件,ClassPathXmlApplicationContext是从类路径读取文件
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("E:\\spring_konw_about\\spring_ioc\\src\\main\\resources\\b01.xml");
Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
System.out.println("------------------------");
System.out.println(bean1.getBean2());
}
}
<!-- spring配置文件-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean1" class="com.xuanxie.spring_ioc.TestApplicationContext.Bean1">
<property name="bean2" ref="bean2"/>
</bean>
<bean id="bean2" class="com.xuanxie.spring_ioc.TestApplicationContext.Bean2"/>
</beans>
1和2总结
// 模拟实现
public class TestApplicationContext {
public static void main(String[] args) {
// 1.创建beanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2.创建xmlBeanDefinitionReader,并将BeanDefinition放置beanFactory中
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 3.通过FileSystemResource或者ClassPathResource读取xml并解析成BeanDefinition,并将其加载到beanFactory
xmlBeanDefinitionReader.loadBeanDefinitions(new FileSystemResource("b01.xml"));
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println("name = " + name);
}
}
}
3.AnnotationConfigApplicationContext
AnnotationConfigApplicationContext的基本使用,我们通过输出可以发现BeanFactory的后处理器已经自动添加上去了,同时把Config也作为Bean添加到容器当中
public class TestApplicationContext {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
for (String name : applicationContext.getBeanDefinitionNames()) {
System.out.println("name = " + name);
}
}
@Configuration
static class Config{
@Bean
public Bean1 bean1(){
return new Bean1();
}
@Bean
public Bean2 bean2(){
return new Bean2();
}
}
static class Bean1{
public void setBean2(Bean2 bean2) {
this.bean2 = bean2;
}
@Autowired
private Bean2 bean2;
public Bean1(){
System.out.println("Bean1.Bean1");
}
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2{
public Bean2(){
System.out.println("Bean2.Bean2");
}
}
}
4.AnnotationConfigServletWebServerApplicationContext
1. 创建Tomcat服务器
2. 创建DispatchServlet
3. 把DispatchServlet和Tomcat联系起来
public class TestApplicationContext {
public static void main(String[] args) {
AnnotationConfigServletWebServerApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
}
@Configuration
static class WebConfig{
/*
1. 创建Tomcat服务器
2. 创建DispatchServlet
3. 把DispatchServlet和Tomcat联系起来
*/
@Bean
public ServletWebServerFactory servletWebServerFactory(){
// 创建一个Tomcat的服务器实现
return new TomcatServletWebServerFactory();
}
@Bean
public DispatcherServlet dispatcherServlet(){
return new DispatcherServlet();
}
@Bean
public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet){
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
}
@Bean("/hello")
public Controller controller(){
return ((request, response) -> {
response.getWriter().print("hello");
return null;
});
}
}
}
Bean的生命周期和模板设计模式
Bean的生命周期
Bean的生命周期一共有4个阶段如下
1. 构造方法
2. 依赖注入
3. 初始化
4. 销毁
// LifeCycleBean.java
@Component
public class LifeCycleBean {
public LifeCycleBean() {
System.out.println("构造方法=>LifeCycleBean.LifeCycleBean");
}
@Autowired
public void autowire(@Value("${JAVA_HOME}") String home){
System.out.println("依赖注入=>home = " + home);
}
@PostConstruct
public void init(){
System.out.println("初始化=>LifeCycleBean.init");
}
@PreDestroy
public void destroy(){
System.out.println("销毁方法=>LifeCycleBean.destroy");
}
}
// SpringIocApplication.java
@SpringBootApplication
public class SpringIocApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class);
context.close();
}
}
Bean后处理器
1. Bean的后处理器主要是对Bean的生命周期过程做适当的扩充
1. 构造阶段
- 构造之前
- 构造之后
2. 注入阶段
- 依赖注入之前
3. 初始化阶段
- 初始化之前
- 初始化之后
4. 销毁阶段
- 销毁之前
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
System.out.println("构造方法之前=>postProcessBeforeInstantiation,这里的返回对象会替换原来的Bean对象");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
System.out.println("构造方法之后=>postProcessAfterInstantiation,如果返回值是false那么会跳过注入阶段");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
System.out.println("依赖注入阶段之前执行方法=>postProcessProperties,@Autowired,@Value注解都是在该阶段执行");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
System.out.println("初始化方法之前=>postProcessBeforeInitialization,返回值会替换掉原来的bean对象,@PostConstruct,@Configuration注解都是在该阶段执行");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
System.out.println("初始化方法之后=>postProcessAfterInitialization,返回值会替换掉原来的bean对象,aop代理增强在该阶段执行");
}
return bean;
}
@Override
public void postProcessBeforeDestruction(Object o, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
System.out.println("销毁方法执行之前=>postProcessBeforeDestruction,如@PreDestory");
}
}
}
模板设计模式
在模板设计模式当中,里面会有变得量也会有不变的量的。不变的那部分相当于我们必走的流程。变的那部分相当于我们可以对其过程的一些扩展方法
1. 定义固定的过程
2. 定义接口方法
3. 创建接受接口变量的集合,并将接口方法运行到固定过程的位置,可能在某个步骤之后,也有可能在某个步骤之前
4. 创建添加接口实现的方法
5. 代码测试
public class templateThink {
public static void main(String[] args) {
MyBeanFactory beanFactory = new MyBeanFactory();
beanFactory.getBean();
System.out.println("-----------------------");
beanFactory.addBeanPostProcessor(bean -> System.out.println("通过Bean后处理器添加的方法,运行在初始化方法之前"));
beanFactory.getBean();
}
static class MyBeanFactory{
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
this.beanPostProcessors.add(beanPostProcessor);
}
public Object getBean(){
/*
下面这是一个模板,任何一个类都需要经过下面的过程,
如果不采用任何设计模式,那么我们当需要在依赖注入的时候做一些事情,
我们要去修改下面的代码,但是对于程序设计来说,应该是更多的开放扩展而少修改
定义了一个接口BeanPostProcessor,并在该类中的所有该接口的实现,都会添加到初始化方法之前
*/
Object bean = new Object();
System.out.println("构造方法执行");
System.out.println("依赖注入执行");
beanPostProcessors.forEach((beanPostProcessor -> beanPostProcessor.inject(bean)));
System.out.println("初始化方法执行");
System.out.println("销毁方法执行");
return bean;
}
}
static interface BeanPostProcessor{
public void inject(Object bean);
}
}
static Object getBean(){
/*
下面这是一个模板,任何一个类都需要经过下面的过程,
如果不采用任何设计模式,那么我们当需要在依赖注入的时候做一些事情,
我们要去修改下面的代码,但是对于程序设计来说,应该是更多的开放扩展而少修改
定义了一个接口BeanPostProcessor,并在该类中的所有该接口的实现,都会添加到初始化方法之前
*/
Object bean = new Object();
System.out.println("构造方法执行");
System.out.println("依赖注入执行");
beanPostProcessors.forEach((beanPostProcessor -> beanPostProcessor.inject(bean)));
System.out.println("初始化方法执行");
System.out.println("销毁方法执行");
return bean;
}
}
static interface BeanPostProcessor{
public void inject(Object bean);
}
}
https://www.bilibili.com/video/BV1P44y1N7QG?p=1&vd_source=1c086e1d8d38cbdc5f4144e6a649f07f