Bean初始化过程

Spring初始化过程,相信很多人都知道,而初始化过程中,我们能够做些什么,现在就来做个总结。
项目地址:https://github.com/esiyuan/spring_sdy.git
导出项目sdy01,如图:
这里写图片描述
图上可以看到,非常简单,代码中没有用Xml的配置方式,而是使用JavaConfig的配置方式,非常的简单。我们可以ConfigSty01入手,这个就是配置文件,相当于xml配置方式的xml文件,其中@Configuration注解,这是标注此类具有xml配置相同的功能,而@ComponentScan提供能进行扫描的功能,spring还提供了很多的注解,进行不同的功能,可以通过@PropertySource注解加载properties文件内容进入上下文;通过@ImportResource可以实现导入xml配置,以及另外的javaconfig配置,进行模块化装配等等。
我们看看这个配置类的详情:

@Configuration  
@ComponentScan(basePackages = "com.esy.sd.tdy01.impl")
public class ConfigSty01 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ConfigSty01.class);
        Producible producter = ac.getBean(Producible.class);
        producter.produce();
        ac.close();
    }
}

从代码中可以看到,使用javaConfig进行配置的话,spring装载上下文,使用的是AnnotationConfigApplicationContext,作用类似ClassPathXmlApplicationContext从类路径进行加载。
我们在看下Producter类,可以看到实现了非常多的接口,而这就是这篇文章的重点,spirng初始化过程会进行哪些动作,而我们又可以做些什么,就是需要实现这些接口才有具有。

@Component
@Log4j
public class Producter implements Producible, InitializingBean, ApplicationContextAware
,BeanClassLoaderAware, BeanNameAware, DisposableBean{
    @Override
    public void destroy() throws Exception {
        log.info("destroy()");
    }
    @PreDestroy
    public void preDestory() {
        log.info("preDestory()");
    }
    @Override
    public void produce() {
        log.info("produce()");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("afterPropertiesSet()");
    }
    @Override
    public void setBeanName(String name) {
        log.info("setBeanName()" + name);       
    }
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        log.info("setBeanClassLoader()" + classLoader);     
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        log.info("setApplicationContext()" + applicationContext);
    }
    @PostConstruct
    public void postContruct() {
        log.info("postContruct()");
    }
}

我们运行ConfigSty01的main方法,会发现打印如下.

2017-02-18 16:56:11,161  INFO annotation.AnnotationConfigApplicationContext (AbstractApplicationContext.java:577)   - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@56606032: startup date [Sat Feb 18 16:56:11 CST 2017]; root of context hierarchy
2017-02-18 16:56:11,351  INFO impl.Producter (Producter.java:41)   - setBeanName()producter
2017-02-18 16:56:11,351  INFO impl.Producter (Producter.java:45)   - setBeanClassLoader()sun.misc.Launcher$AppClassLoader@5200089
2017-02-18 16:56:11,351  INFO impl.Producter (Producter.java:50)   - setApplicationContext()org.springframework.context.annotation.AnnotationConfigApplicationContext@56606032: startup date [Sat Feb 18 16:56:11 CST 2017]; root of context hierarchy
2017-02-18 16:56:11,351  INFO impl.Producter (Producter.java:54)   - postContruct()
2017-02-18 16:56:11,351  INFO impl.Producter (Producter.java:37)   - afterPropertiesSet()
2017-02-18 16:56:11,376  INFO impl.Producter (Producter.java:33)   - produce()
2017-02-18 16:56:11,376  INFO annotation.AnnotationConfigApplicationContext (AbstractApplicationContext.java:957)   - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@56606032: startup date [Sat Feb 18 16:56:11 CST 2017]; root of context hierarchy
2017-02-18 16:56:11,377  INFO impl.Producter (Producter.java:29)   - preDestory()
2017-02-18 16:56:11,377  INFO impl.Producter (Producter.java:25)   - destroy()

由此可以看出,spring容器进行javabean管理的时候,并不是只是简单的实例化,还提供和容器相关的功能,例如:BeanNameAware、BeanClassLoaderAware、ApplicationContextAware接口,当我们的类实现了这些接口后,同时也就和spring进行了强耦合(如今很少会有不用spring的项目,基于spring的开发估计都成了规范,还会有谁关心是否spring耦合了呢,重点是项目能够运行)。通过BeanNameAware我们可以获取spring容器中此类实例的名字,通过BeanClassLoaderAware我们可以获取加载此类的类加载器,这两个好像不怎么常见,而ApplicationContextAware这个就非常有用了,实现了它,那么容器实例化类后,会将spring的上下文传递给此实例,通过spring上下文,我们就可以获取到spring容器中的其他bean实例,对于有些场景,需要在项目中利用名称获取其他bean的地方,就非常有用了。
再来,就是spring生命周期相关的接口了,实现了InitializingBean接口,spring容器会在bean实例化后进行afterPropertiesSet方法的调用,相同的功能,我们也能够通过@PostConstruct注解实现,可能对于大家最常用的应该是配置文件中init属性指定方法,而实现了DisposableBean接口,容器会销毁前进行destroy方法的调用,同样的也可以通过@PreDestroy注解的方式以及配置文件中 destroy-method属性进行指定,这些都是spring提供的生命周期管理的方式,具体的选择,就需要看大家的使用习惯了。
最后总结下,bean实例化的流程。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值