互联网架构-Spring5.0源码深度解析-021:AnnotationConfigApplicationContext源码解析&SpringBean的生命周期

1 BeanFactory与ApplicationContext区别

AnnotationConfigApplicationContext注解启动原理
Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。它们都可以代表Spring容器,Spring容器是生成Bean实例的工厂,并且管理容器中的Bean。

BeanFactory与ApplicationContext之间区别是什么?

  1. BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的生命周期。
  2. ApplicationContext除了提供上述BeanFactory所能提供的功能外,还提供了更完整的框架功能:
    a. 国际化支持
    b. 资源访问:Resource rs = ctx.getResource(“classpath:config.properties”), “file:c:/config.properties”
    c. 事件传递:通过实现ApplicationContextAware接口
  3. 常用的获取ApplicationContext的方法:
    ClassPathXMLApplicationContext:从classpath的xml配置文件创建,可以从jar包中读取配置文件;
    AnnotationConfigApplicationContext:基于注解使用,不需要配置文件,采用java配置类和各种注解来配置
public class V2Spring {
    public static void main(String[] args) {
        // 1.基于注解方式实现启动
        ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        // 2.使用xml启动的话
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean");
        // 生成类图  ctrl + alt + u
        // ApplicationContext其实就是上下文操作,AnnotationConfigApplicationContext和ClassPathXmlApplicationContext都是基于它的扩展类
        // ApplicationContext继承BeanFactory实现扩展的功能
    }
}

2 AnnotationConfig启动流程源码分析

AnnotationConfigApplicationContext源码分析
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 单例与多例对象是如何初始化的

课题内容:
1.SpringBean的生命周期有那些?
2.Spring的BeanPostProcessors作用
3.Spring的底层如何获取Spring上下文

单例和多例是在什么时候初始化的? 默认的情况下
单例默认情况下是在容器被加载的时候就会被初始化;
多例是在每次获取bean对象的时候就会去初始化;
底层使用beanFactory.preInstantiateSingletons();预执行初始化所有非懒加载的单例对象
在这里插入图片描述

4 对象的初始化与销毁过程01

SpringBean的生命周期
Bean的创建(执行构造函数)->初始化(自定义init方法)->销毁过程。
可以自定义对象初始化与销毁的方法

@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")

对象的初始化和销毁

  1. 对象的初始化
    对象创建完成,并赋值好,调用初始化方法
  2. 对象的销毁
    单实例:容器关闭的时候(调用close方法)
    多实例:容器不会管理这个bean;容器不会调用销毁方法
@Component
//@Scope("prototype")
public class UserEntity {
    public UserEntity(){
        System.out.println(">>UserEntity无参构造函数执行...");
    }

    /**
     * initMethod是在无参构造函数之后执行
     */
    private void initMethod() {
        System.out.println(">>UserEntity initMethod 执行...");
    }

    private void destroyMethod() {
        System.out.println(">>UserEntity destroyMethod 执行...");
    }
}
@Configuration
@ComponentScan("com.mayikt.entity")
public class MyConfig {

    /**
     * initMethod 指定初始化方法执行 创建对象成功执行initMethod方法
     * destroyMethod 指定销毁方法
     * @return
     */
    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public UserEntity userEntity() {
        return new UserEntity();
    }
}
public class Test001 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
//        annotationConfigApplicationContext.getBean("userEntity");

        /**
         * bean初始化 指的就是对象已经创建,里面所有的set方法都执行完毕了;可以指定方法进行执行
         */
        // 调用close方法销毁单例对象  Map集合存储bean对象 底层调用clear()
        annotationConfigApplicationContext.close();
    }
}

运行结果
在这里插入图片描述

5 对象的初始化与销毁过程02

初始化和销毁的方法
方法一:通过@Bean指定init-method和destroy-method
方法二:通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);

@Component
public class MemberEntity implements InitializingBean, DisposableBean {

    public MemberEntity(){
        System.out.println("MemberEntity >>无参构造函数");
    }

    // afterPropertiesSet等同于initMethod方法
    // 对象创建->给对象属性赋值 set方法全部执行完成之后走afterPropertiesSet
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MemberEntity >>afterPropertiesSet");

    }

    @Override
    public void destroy() throws Exception {
        System.out.println("MemberEntity >>destroy");
    }
}

运行结果:
在这里插入图片描述
方法三:可以使用JSR250;(java规范自带)
@PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作

@Component
public class MemberEntity2 {

    public MemberEntity2() {
        System.out.println("MemberEntity2 >>无参构造函数");
    }
    @PostConstruct
    public void afterPropertiesSet() throws Exception {
        System.out.println("MemberEntity2 >>afterPropertiesSet");
    }
    @PreDestroy
    public void destroy() throws Exception {
        System.out.println("MemberEntity2 >>destroy");
    }
}

运行结果:
在这里插入图片描述

6 ApplicationContextAware接口

过滤器中,是否可以使用注解方式获取bean的对象 不可以(自己单独获取上下文applicationContext)
BeanPostProcessor(后置处理器作用:对bean的初始化实现增强)
实现ApplicationContextAware接口

@Component
public class MyApplicationContext implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    /**
     * spring底层中为什么实现ApplicationContextAware接口 就能拿到applicationContext 靠的就是后置处理器
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MemberEntity memberEntity = applicationContext.getBean("memberEntity", MemberEntity.class);
        System.out.println("memberEntity:" + memberEntity);
    }
}

配置类中增加注入语句@Import({MyApplicationContext.class})
对象初始化并且赋值完成之后走到setApplicationContext方法里面
运行结果:
在这里插入图片描述
实现ApplicationContextAware类,可以获取到applicationContext对象

@Component
public class PayEntity implements ApplicationContextAware {
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("获取到applicationContext对象");
    }
}

底层代码执行流程:
在这里插入图片描述

7 BeanNameAware与BeanFactoryAware区别

在这里插入图片描述
在这里插入图片描述
测试BeanNameAware与BeanFactoryAware使用
(作用:拿到注入类的beanName/beanClassLoader/beanFactory)

@Component
public class PayEntity implements BeanNameAware, BeanFactoryAware {
    public PayEntity() {
        System.out.println("1.对象的实例化完成..");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("2.beanName:" + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3.beanFactory:" + beanFactory);
    }
}

运行结果:
在这里插入图片描述

8 BeanPostProcessor的作用

BeanPostProcessor的作用是对Bean的对象实现增强,在方法之前和之后进行处理

@Component
public class PayEntity implements BeanNameAware, BeanFactoryAware, InitializingBean {
    public PayEntity() {
        System.out.println("1.对象的实例化完成..");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("2.beanName:" + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3.beanFactory:" + beanFactory);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("4.bean init方法执行..");
    }

}
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    // BeanPostProcessor后置处理器

    // 执行自定义init方法之前进行处理
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行init方法之前处理.." + beanName);
        return null;
    }

    // 执行自定义init方法之后进行处理
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行init方法之后处理.." + beanName);
        return null;
    }
}

运行结果:
在这里插入图片描述

9 SpringBean的生命周期总结01

Spring的生命周期
1.实例化对象;
2.Setter注入,执行Bean的属性依赖注入;
3.BeanNameAware的setBeanName(),如果实现该接口,则执行其setBeanName方法;
4.BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法;
5.BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法;
6.InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行afterPropertiesSet()方法;(等同于Bean定义文件中定义init-method)
7.BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法;
8.DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法;
9.Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用”destroy-method”定义的方法。

10 SpringBean的生命周期总结02

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值