Spring的核心接口

Spring Bean的生命周期

Bean的生命周期就是Bean创建—销毁—初始化的过程,这些都由容器管理

我们可以自定义销毁和初始化的方法,特别在配置数据源的时候很有用

    @Bean(initMethod="init",destroyMethod="detory")
    public Car car(){
        return new Car();
    }

AnnotatedBeanDefinitionReader 在spring上下文初始化的时候调用,

AnnotatedBeanDefinitionReader#register 可以往bean工厂注册beanDefinition,AnnotatedBeanDefinitionReader自己在初始化的时候会往bean工厂注册spring自带的beanFactoryPostProcessor和beanPostProcessor,

这些注册到bean工厂的list中,后面会使用到。

ClassPathBeanDefinitionScanner在spring启动的时候完成初始化的:

ClassPathBeanDefinitionScanner作用就是将指定包下的类通过一定规则过滤后 将Class 信息包装成 BeanDefinition 的形式注册到IOC容器中。

扫描类路径下的候选Component,构造BeanDefinition对象(实际为ScannedGenericBeanDefinition)

利用BeanDefinitionRegister注册BeanDefinition到bean工厂中,BeanDefinitionRegister是spring默认bean工厂DefaultListableBeanFactory的一个接口,用于注册BeanDefinition;

    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        this();
        register(annotatedClasses);
        refresh();
    }
  ————————————————————————————————————this()
    public AnnotationConfigApplicationContext() {
        //在IOC容器中初始化一个 注解bean读取器AnnotatedBeanDefinitionReader
        this.reader = new AnnotatedBeanDefinitionReader(this);
        //在IOC容器中初始化一个 按类路径扫描注解bean的 扫描器
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

我们从Spring核心接口的角度谈一下Spring Bean创建的过程,也就是Spring的生命周期

【ImportBeanDefinitionRegistrar接口】调用registerBeanDefinitions
【BeanFactoryPostProcessor接口】调用postProcessBeanFactory
  ... constructor...
【BeanNameAware接口】调用setBeanName方法
【BeanFactoryAware接口】调用setBeanFactory方法
【BeanPostProcessor接口】调用postProcessBeforeInitialization方法对属性进行更改
【InitializingBean接口】调用afterPropertiesSet方法
【init-method】调用<bean>的init-method属性指定的初始化方法
【BeanPostProcessor接口】调用postProcessAfterInitialization
【DiposibleBean接口】调用destroy方法
【destroy-method】调用<bean>的destroy-method属性指定的初始化方法

参考文章CSDN:https://www.cnblogs.com/javazhiyin/p/10905294.html

参考文章知乎:https://www.zhihu.com/question/38597960/answer/247019950?utm_source=wechat_session

ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrar接口是spring的扩展点之一,

它可以支持我们自己写的代码封装成BeanDefinition对象;实现此接口的类会回调postProcessBeanDefinitionRegistry方法,注册到spring容器中。

把bean注入到spring容器不止有 @Service @Component等注解方式;还可以实现此接口。

接口的使用很简单,使用@Import注解导入这个类即可。

通过调用它的registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)方法,

AnnotationMetadata :当前类的注解信息

BeanDefinitionRegistry :BeanDefinition注册类

BeanFactoryPostProcesser

BeanFactoryPostProcesser和BeanPostProcesser名字很类似 这个是BeanFactory的后置处理器也是Spring的扩展点

执行时机:这个接口的作用是在Spring上下文的注册Bean定义的逻辑都跑完后,但是所有的Bean都还没真正实例化之前调用。

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

这个方法的主要用途就是通过注入进来的BeanFactory,在真正初始化Bean之前,再对spring上下文做一些动态修改。增加或者修改某些Bean定义的值,甚至再动态创建一些BeanDefinition都可以。

BeanDefinitionRegistryPostProcessor 是BeanFactoryPostProcesser的子类和父类相比 它额外定义了一个新的方法postProcessBeanDefinitionRegistry()

执行时机:这个子接口的方法postProcessBeanDefinitionRegistry会被Spring先于postProcessBeanFactory这个方法执行。

不过呢,其实这2个方法都是注入的spring的上下文,只不过声明类型不同罢了。所以可以做的事一模一样。

参考文章简书:https://www.jianshu.com/p/899bd8089352

ApplicationContextAware接口以及XXXAware接口

通俗的解释:如果在某个类里面想要使用spring的一些东西,就可以通过实行XXXAware接口告诉spring,spring会到最后给你送过来,而接收的方式是通过实现接口唯一的方法set-XXX。
比如,有一个类想要使用当前的ApplicationContext,那么我们只需要让它实现ApplicationContextAware接口,然后实现接口中唯一的方法void setApplicationContext(ApplicationContext applicationContext)就可以了,spring会自动调用这个方法将applicationContext传给我们,我们只需要接收就可以了。

BeanPostProcesser

BeanPostProcesser的作用是在Bean初始化前后处理一些工作

BeanPostProcesser名字虽然叫后置处理器,但是提供了两个方法postProcessBeforeInitialization和postProcessAfterInitialization,在Bean初始化之前和初始化之后分别调用,

我们的Bean可以实现此接口,然后重写上面两个方法

BeanPostProcesser调用原理:

像这种方法前后加一些东西的,一开始想到的是AOP,源码上看起来并不是AOP,而是在执行InitMethod(初始化方法)的前后分别调用两个方法

Spring对BeanPostProcesser的一些使用

BeanValidationPostProcessor  在Web里面对数据校验用的比较多

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!this.afterInitialization) {
            doValidate(bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (this.afterInitialization) {
            doValidate(bean);
        }
        return bean;
    }

 AutowiredAnnotationBeanPostProcessor 在对象创建完之后处理Autowired注解

ApplicationListener

ApplicationListener监听容器中发布的事件,事件驱动模型的开发

理解ApplicationListener 首先了解下观察者模式

现在我们自己发布一个事件的流程

1.首先写一个Listener实现ApplicationListener接口,接口中可以拿到事件源对象。相当于观察者模式的Observe实现类

@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

    @Override
    public void onApplicationEvent(MyApplicationEvent event) {
        System.out.println("我接收到事件======"+event.getInfo());
    }

2. 然后定义一个事件实现类,和观察者模式一样 拥有事件原对象

public class MyApplicationEvent extends ApplicationEvent {
    private String info;

    public MyApplicationEvent(Object source,String info) {
        super(source);
        this.info=info;
        System.out.println("事件构造");
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

3. 单元测试最后把事件发布出去即可 相当于观察者模式中的c.wakeUp();(小孩哭这个动作)

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);
        System.out.println("发布事件");
        applicationContext.publishEvent(new MyApplicationEvent(applicationContext,"开始吃饼干") {
        });
        applicationContext.close();
    }

打印结果:

发布事件
事件构造
我接收到事件======开始吃饼干

Spring的监听器的实现原理和Observe设计模式应该一样,即循环所有的观察者,对分别调用响应事件的方法。这里的publishEvent就相当于观察者模式中的小孩哭

    public void publishEvent() {
        cry = true;

        wakeUpEvent event = new wakeUpEvent(System.currentTimeMillis(), "bed", this);

        for(Observer o : observers) {
            o.actionOnWakeUp(event);
        }
    }

BeanFactory和FactoryBean的区别

顾名思义:BeanFactory是Bean工厂,是一个工厂 参考工厂的设计模式,FactoryBean是一个Bean 是一个java类

FactoryBean接口对于Spring框架占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来的便利。

该接口中定义了三个方法

    T getObject() throws Exception;

    Class<?> getObjectType();

    boolean isSingleton();
posted @ 2020-05-26 19:29  palapala  阅读(1507)  评论(0编辑  收藏  举报