Spring中init-method和destroy-method的四种方式

  • Post author:
  • Post category:其他


在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等。

要用这两个方法,自然先要知道这两个方法究竟是干嘛用的。而从字面意思就很容易理解,一个是加载,一个是销毁。

下边就正式代码演示几种创建方式:

一、@Bean注解方式

public class Person {

    private String name;

    private Integer age;

    // 无参构造器
    public Person() {
        System.out.println("Person NoConstructor");
    }

    // 充当init method
    public void init() {
        System.out.println("Person init-method");
    }

    // 充当destroy method
    public void destroy() {
        System.out.println("Person destroy-method");
    }
}

这里很显然只是一个普通的java类,拥有一个无参构造和另外两个方法。

需要注意的是,这里的init和destroy两个方法名实际上是可以随意取得,不叫这个也没有问题,只不过算是一种约定俗称,一般都是这样叫。

另外我们也知道,这个构造方法也是可以不要的,因为会隐式的自动创建,但是为了更清楚的看到init和destroy是什么时候执行,我们就显示的写出来。

创建好了这个类,我们就可以使用@Bean注解的方式指定两个方法,以让他们生效。

@Configuration
@ComponentScan(value = "com.best")
public class AppConfig {

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Person getPerson() {
        return new Person();
    }
}

这里边的@Configuration注解是告诉spring这个类是一个配置类,相当于我们的xml文件

@ComponentScan则是指定需要spring来扫描的包,相当于xml中的context:component-scan属性

@Bean后边的initMethod和destroyMethod就是在声明这是一个bean的同时指定了init和destroy方法,方法名从功能实现上来说可以随意。

到这里我们就已经用第一种方式写好了,为了验证成功与否,再写一个main方法验证一下:

public class Test {
	public static void main(String[] args) {

		/**
		 * 1.把类扫描出来--扫描以后干了什么事情
		 * 2.把bean实例化
		 */
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		Person person = applicationContext.getBean(Person.class);
		System.out.println(person.getClass().getName());
		applicationContext.close();
	}
}

运行之后结果:


根据打印顺序可以看到,首先是构造函数,也就是创建了bean,紧接着执行了init,然后再context.close要销毁bean之前又执行了destroy。

二、Xml配置方式

这种方式实际上是和第一种对应的,只不过细节上略有改变而已,首先,创建的java类完全一样:

public class Person {

    private String name;

    private Integer age;

    // 无参构造器
    public Person() {
        System.out.println("xmlPerson NoConstructor");
    }

    // 充当init method
    public void init() {
        System.out.println("xmlPerson init-method");
    }

    // 充当destroy method
    public void destroy() {
        System.out.println("xmlPerson destroy-method");
    }
}

不同的地方就在于,第一个例子中是使用注解告诉spring这个类相当于一个配置文件,而这里则是实实在在的配置文件spring.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!--配置Person对象创建-->
	<bean id="xmlPerson" class="com.best.entity.Person" init-method="init" destroy-method="destroy">
	</bean>
</beans>

这个配置大概也能算是spring.xml中最简单的一个配置了吧,除开必要的文件头,就只有一个bean,而且bean里边也只有id,calss和init以及destroy方法。

因为简单,所以一目了然,id只是为了其他地方引用,class是指定这个bean对应的类,而后边两个属性则和用@Bean声明时一模一样。

因为这里声明bean和指定两个方法是用的xml配置,因此在测试的时候也就需要稍微有一点点改变:

public class TestXml {

	public static void main(String[] args) {
		// 用配置文件启动一个ApplicationContext
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("test1.xml");
		// 从context中取出我们的Bean,而不是用new User()这种方式
		Person person = (Person) applicationContext.getBean("xmlPerson");
		System.out.println(person.getClass().getName());
		applicationContext.close();
	}
}

区别在于这里直接加载了配置文件,而不是java类,使用的是ClassPathxXmlApplicationContext而不是AnnotationConfigApplicationContext。

结果如下:

三、JSR-250注解的方式(需要导入jsr250-api的jar包)

首先依然是创建一个拥有构造方法在内的三个方法的java类:

public class Person {

    private String name;

    private Integer age;

    // 无参构造器
    public Person() {
        System.out.println("Person NoConstructor");
    }

    // 充当init method
    // 初始化方法的注解方式 等同于init-method
    @PostConstruct
    public void init() {
        System.out.println("Person init-method");
    }

    // 充当destroy method
    // 销毁方法的注解方式 等同于destroy-method
    @PreDestroy
    public void destroy() {
        System.out.println("Person destroy-method");
    }
}

很显然,这里和上一个类不同的是,在init和destroy方法上加入了两个注解,@PostConstruct和上边@Bean后的initMethod相同,而@PreDestroy则是和destroyMethod做用相同。

既然这里有了区别,已经指定了init method和destroy method,那么后边声明bean的时候自然也会有不同,也就不需要再指定一遍:

@Configuration
@ComponentScan(value = "com.best")
public class AppConfig {

    @Bean
    public Person getPerson() {
        return new Person();
    }
}

所以,如上代码中只需要简单的声明这是一个bean就可以了,类上边的两个注解和上一个例子中的意思相同。

再测试一下:

public class Test {
	public static void main(String[] args) {

		/**
		 * 1.把类扫描出来--扫描以后干了什么事情
		 * 2.把bean实例化
		 */
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		Person person = applicationContext.getBean(Person.class);
		System.out.println(person.getClass().getName());
		applicationContext.close();
	}
}

四、 InitializingBean和DisposableBean

Spring bean 通过实现 InitializingBean ,DisposableBean 接口实现初始化方法和销毁前操作

@Component
public class Student implements InitializingBean, DisposableBean {

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

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet");
    }
}
@Configuration
@ComponentScan(value = "com.best")
public class AppConfig {

}
public class Test {
	public static void main(String[] args) {

		/**
		 * 1.把类扫描出来--扫描以后干了什么事情
		 * 2.把bean实例化
		 */
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		Student student = applicationContext.getBean(Student.class);
		System.out.println(student.getClass().getName());
		applicationContext.close();
	}
}

运行结果:


参考博客



参考博客



版权声明:本文为qq_38826019原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。