自定义初始化方法init java spring初始化自定义bean_初始化


写在之前

         最近没事在浏览Spring官网,简单写一些相关的笔记,这篇文章整理Spring自定义Bean。并不包所有技术点,只是记录有收获的内容,例如从背景知识了解到SpringFramework5.1开始,Spring需要JDK8+,并为JDK11LTS提供开箱即用的支持


Spring框架提供了许多接口,可以用来定制bean的性质

1.自定义Bean行为

从Spring2.5开始,您有三种控制bean生命周期行为的选项:

  • InitializingBean和DisposableBean回调接口
  • 自定义init和destroy方法
  • @PostConstruct和@PreDestroy注释

1.1Bean初始化回调

        Spring的 InitalizingBean接口允许bean在容器设置了bean的所有必要属性后执行执行初始化工作,InitalizingBean接口仅有一个afterPropertiesSet方法,在Spring初始化后,执行完所有属性设置方法(setXxx)后将调用afterPropertiesSet

package org.springframework.beans.factory;
public interface InitializingBean {

	void afterPropertiesSet() throws Exception;
}

例如

ExampleBean继承了接口InitalizingBean,并可在afterPropertiesSet方法中自定义一些特殊处理,XML中并不需要做特殊配置

public class InitExampleBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        // do some initialization work
    }
}
<bean id="initExampleBean" class="examples.InitExampleBean"/>

        Spring虽然可以通过InitializingBean完成一个bean初始化后对这个bean的回调,但是这种方式要求bean实现Spring提供的 InitializingBean接口。这个bean的代码就和Spring耦合到一起了。通常情况下不鼓励bean直接实现InitializingBean,可以使用Spring提供的init-method的功能来执行一个bean 子定义的初始化方法。

public class ExampleBean {

    public void init() {
        // do some initialization work
    }
}
<!-- init-method 设置初始化方法-->
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>

Spring 可以通过注解@PostConstruct来声明初始化方法,@PostConstruct只能修饰一个非惊呆他的void方法

public class CachingMovieLister {

    @PostConstruct
    public void init() {
        //do something
    }
}

注意: 如果InitializingBean和init-method可以一起使用,Spring会先处理InitializingBean再处理init-method。

1.2Bean销毁回调

Spring的 DisposableBean接口允许bean在容器中销毁时回调,DisposableBean接口仅有一个destory方法,该方法在BeanFactory在销毁单例时调用,此接口的异常只会被记录在日志中不会抛出,保证其他bean可以释放它们的资源

package org.springframework.beans.factory;
public interface DisposableBean {

	void destroy() throws Exception;
}

和 InitializingBean相似, 并不建议使用继承DisposableBean接口实现销毁时的自定义操作。 因为它会将Bean的代码和Spring代码耦合在一起,建议使用destroy-method属性,例如

public class ExampleBean {

    public void cleanup() {
        // do some destruction work
    }
}
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>

 Spring 可以通过注解@PreDestroy来声明销毁方法,@PreDestroy只能修饰一个非惊呆他的void方法

public class CachingMovieLister {

    @PreDestroy
    public void clearMovieCache() {
        // do some clear
    }
}

这样,destroy-method和@PreDestroy不会将Bean代码和Spring代码耦合在一起

1.3默认初始化和销毁方法

初始化和销毁方法回调时,您通常使用init()、initialize()、dispose()等名称编写方法。一般情况下方法的名称在整个项目中都是标准化的,开发人员使用相同的方法名称并确保一致性。这样就可以设置默认的初始化或者销毁方法

public class DefaultBlogService implements BlogService {

    private BlogDao blogDao;
    public void setBlogDao(BlogDao blogDao) {
        this.blogDao = blogDao;
    }

    public void init() {
        if (this.blogDao == null) {
            throw new IllegalStateException("The [blogDao] property must be set.");
        }
    }
}

 配置顶层<beans>元素属性上存在默认的init-method属性,Spring IoC容器将bean类上名为init的方法识别为初始化方法回调。在创建和组装bean时,如果bean类有这样的方法,则会在适当的时候调用它

<beans default-init-method="init">

    <bean id="blogService" class="com.something.DefaultBlogService">
        <property name="blogDao" ref="blogDao" />
    </bean>

</beans>

bean类已经具有与约定不同的回调方法,则可以通过使用<bean>本身的init-method="init"方法来覆盖默认方法

2.执行顺序

如果为一个bean配置了多个生命周期机制,并且每个机制都配置了不同的方法名,那么每个配置的方法都会按照本说明后面列出的顺序运行

2.1初始化Bean方法先后顺序 

  1. @PostConstruct注释的方法
  2. InitializingBean回调接口定义的afterPropertiesSet()
  3. 自定义配置的init()方法

2.2销毁Bean方法先后顺序

  1. @PreDestroy注释的方法
  2. destroy(),由DisposableBean回调接口定义
  3. 自定义配置的destroy()方法

上一篇:Spring中的依赖关系(DI)