一文掌握Spring核心IOC及其扩展点

spring 核心一 IOC容器

spring的核心是IOC容器,即控制反转Inverse of control,将bean实例统一管理,无需在代码里手动New对象。

IOC构建流程

1、整体流程

1、获取一个新的bean工厂,通常是ApplicationContext,就是IOC容器

2、加载解析bean配置,将解析的bean封装到BeanDefinition中,并放到本地缓存中。

3、将bean放到IOC容器,包括如下:

​ (1) 实例化所有的bean(非懒加载)

​ (2) bean的属性填充

​ (3) 初始化bean

4、刷新ApplicationContext。

2、流程细分
(1) 获取一个新的bean工厂

​ 通常是ApplicationContext,就是IOC容器,ApplicationContext是BeanFactory的实现类,是spring最核心的接口。用getBean来加载bean。BeanFactory相当于是IOC的基础类,。

注意FactoryBean是另一个东西,可以用来手动注入类实例

事例通过FactoryBean注入类实例

/**
 *
 */
//1. 这里的接口泛型参数为要注入Bean的类型
public class MyFactoryBean implements FactoryBean<Person> {
    //2.重写的第一个方法返回Bean的实例
    @Override
    public Person getObject() throws Exception {
        return new Person("123");
    }

    //3.重写的第二个方法返回Bean的类型
    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }

    //4.重写的第三个方法返回一个boolean值,决定该Bean的类型是单例还是多实例。这里返回true,为单例。
    @Override
    public boolean isSingleton() {
        return true;
    }
}
public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
@Configuration
public class FactoryBeanConfig {
    /**
     * 把MyFactoryBean类的Bean注入容器,即实现了把Person类Bean注入容器。
     * @return
     */
    @Bean
    public MyFactoryBean PersonBean(){//这里的方法名称是Person类Bean的ID
        return new MyFactoryBean();
    }
}

测试代码

ApplicationContext applicationContext = SpringApplication.run(BasicApplication.class, args);

// 测试通过继承factorybean方式注入IOC容器
Person personBean = (Person)applicationContext.getBean("PersonBean");
System.out.println(personBean.getName());
(2) 加载解析bean配置

​ 加载的bean配置解析封装到BeanDefinition中,并放到本地缓存中。加载完所有bean配置后触发如下方法:

实现接口BeanFactoryPostProcessor#postProcessBeanFactory方法

/**
 * postProcessBeanFactory 方法,在步骤二加载完bean的配置后触发,即在步骤三前。
 * 通常可以使用这个方法来加载自己的bean定义
 */
@Component
public class BeanFactoryPostProcessorTest implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("此处通常可以使用这个方法来加载自己的bean定义");
    }
}
(3) 将bean放到IOC容器

​ 步骤一:实例化所有的bean(非懒加载方式)

​ 步骤二:bean的属性填充

初始化前触发方法有:

​ 1、实现接口 BeanPostProcessor#postProcessBeforeInitialization方法

@Component
public class BeanPostProcessorTest implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException    {
        System.out.println("执行bean的初始化方法前触发");

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

​ 2、实现接口 InitializingBean#afterPropertiesSet方法

/**
 * afterPropertiesSet 方法,在bean的属性填充之后,初始化方法(init-method)之前被触发
 * 该方法的作用基本等同于init-mehod,主要用于执行初始化相关操作。
 */
@Component
public class InitializingBeanTest implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("在bean的属性填充之后,初始化方法(init-method)之前被触发");
    }
}

​ 3、注入类指定初始化方法 @Bean指定initMethod

@Configuration
public class ConfigBean {
    // initMethod指向Cat里的init()方法,destroyMethod指向Cat里的destroy()方法
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Cat cat() {
        return new Cat();
    }
}

public class Cat {
    public Cat() {
        System.out.println("Cat‘s 构造方法。。。");
    }

    public void init() {
        System.out.println("Cat‘s init()方法。。。");
    }
}

​ 4、类中指定@PostConstruct注解指定方法

public class Cat {
   @PostConstruct
    public void postConstruct() {
        System.out.println("Cat‘s postConstruct()方法。。。");
    }
 }

​ 步骤三:初始化bean

初始化后触发:1、实现接口BeanPostProcessor#postProcessAfterInitialization方法

/**
 * postProcessBeforeInitialization方法,执行bean的初始化方法前触发
 * postProcessAfterInitialization方法,执行bean的初始化方法后触发
 */
@Component
public class BeanPostProcessorTest implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行bean的初始化方法前触发");

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行bean的初始化方法后触发");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

​ 2、实现接口 DisposableBean#destroy方法(销毁前)

/**
 * destroy 方法,在bean被销毁之前被触发,相当于 destroyMethod 方法
 *
 */
@Component
public class DisposableBeanTest implements DisposableBean {
    @Override
    public void destroy() throws Exception {

    }
}

​ 3、注入类指定初始化方法 @Bean指定destroyMethod(销毁前)

@Configuration
public class ConfigBean {
    // initMethod指向Cat里的init()方法,destroyMethod指向Cat里的destroy()方法
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Cat cat() {
        return new Cat();
    }
}
public class Cat {
	  public void destroy() {
        System.out.println("Cat‘s destroy() 方法。。。");
    }
}

​ 4、类中指定@PreDestroy注解指定方法(销毁前)

public class Cat {
	 @PreDestroy
    public void preDestroy() {
        System.out.println("Cat‘s preDestroy()方法。。。");
    }
}

​ 5、实现接口SmartLifecycle#start()方法

/**
 * 当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法)。
 */
@Component
public class SmartLifecycleTest implements SmartLifecycle {
    private boolean isRunning = false;


    /**
     * 步骤一:
     * 当上下文被刷新(所有对象已被初始化之后)时,将调用此方法
     * 1、默认生命周期处理器将检查每个SmartLifecycle对象的 isAutoStartup()方法返回的布尔值。
     * 如果为“true”,则start()方法会被调用,在 SmartLifecycle接口中默认值为true;
     * @return
     */
    @Override
    public boolean isAutoStartup() {
        return true;
    }
    /**
     * 步骤二:
     * 如果工程中有多个实现接口SmartLifecycle的类,则这些类的start的执行顺序按getPhase方法返回值从小到大执行。<br/>
     * 例如:1比2先执行,-1比0先执行。 stop方法的执行顺序则相反,getPhase返回值较大类的stop方法先被调用,小的后被调用。
     */
    public int getPhase() {
        // 默认为0
        return 0;
    }

    /**
     * 步骤三:
     * 1. 我们主要在该方法中启动任务或者其他异步服务,比如开启MQ接收消息<br/>
     */
    @Override
    public void start() {
        System.out.println("start");
        // 执行完其他业务后,可以修改 isRunning = true
        isRunning = true;
    }


    /**
     * SmartLifecycle子类的才有的方法,当 isRunning() 方法返回true时,该方法才会被调用。
     */
    @Override
    public void stop(Runnable callback) {
        System.out.println("stop(Runnable)");
        callback.run();

        isRunning = false;
    }

    /**
     * 接口Lifecycle的子类的方法,只有非SmartLifecycle的子类才会执行该方法。<br/>
     * 1. 该方法只对直接实现接口Lifecycle的类才起作用,对实现SmartLifecycle接口的类无效。<br/>
     * 2. 方法stop()和方法stop(Runnable callback)的区别只在于,后者是SmartLifecycle子类的专属。
     */
    @Override
    public void stop() {
        System.out.println("stop()");

        isRunning = false;
    }

    /**
     * 1. 只有该方法返回false时,start方法才会被执行。<br/>
     * 2. 只有该方法返回true时,stop(Runnable callback)或stop()方法才会被执行。
     */
    @Override
    public boolean isRunning() {
        return isRunning;
    }


}
(4) 刷新ApplicationContext

​ 刷新IOC容器,执行refresh方法

刷新IOC容器前触发:
1、实现接口ApplicationContextInitializer#initialize的方法

/**
 *
 *
 * initialize 方法,在spring容器刷新前触发,也就是refresh方法前触发。
 */
@Component
public class ApplicationContextInitializerTest implements ApplicationContextInitializer {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("刷新IOC容器前可以加自己的扩展点。");
    }
}

刷新IOC容器完成后触发:
1、实现接口ApplicationListener#onApplicationEvent的方法可以监听容器刷新完成事件ContextRefreshedEvent

/**
 * onApplicationEvent 监听容器启动过程中的事件
 * 事件一如ContextRefreshedEvent :上下文刷新完毕的事件,通常用于IOC容器构建结束后处理一些逻辑
 */
@Component
public class ApplicationListenerTest implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if(event instanceof ContextRefreshedEvent){
            // IOC容器启动完成刷新事件
            System.out.println("ContextRefreshedEvent :上下文刷新完毕的事件,通常用于IOC容器构建结束后处理一些逻辑");
        }
        System.out.println("spring event :"+event);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习是生活的调味剂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值