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

周末对这两个方法进行了一点学习和整理,倒也不是专门为了这两个方法,而是在巩固spring相关知识的时候提到了,然后感觉自己并不是很熟悉这个,便好好的了解一下。

根据特意的去了解后,发现实际上可以有三种方式来实现init method和destroy method。

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

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

一、@Bean注解方式:

首先要创建一个至少拥有两个方法的类,一个方法充当init method,另一个充当destroy method。

package springTest2;
public class Test1 {
    public void init() {
        System.out.println("this is init method1");
    }
    public Test1() {
        super();
        System.out.println("构造函数1");
    }
    public void destroy() {
        System.out.println("this is destroy method1");
    }
}

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

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

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

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

package springTest2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("springTest2")
public class ConfigTest {
    @Bean(initMethod = "init", destroyMethod = "destroy")
    Test1 test1() {
        return new Test1();
    }
}

这里边的@Configguration注解是告诉spring这个类是一个配置类,相当于我们的xml文件,@ComponentScan则是指定需要spring来扫描的包,相当于xml中的context:component-scan属性。

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

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

package springTest2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigTest.class);
                System.out.println("#################################");
        context.close();
    }
}

运行之后结果如图:



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

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

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

package springTest2;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Test2 {
    @PostConstruct
    public void init() {
        System.out.println("this is init method2");
    }
    public Test2() {
        super();
        System.out.println("构造函数2");
    }
    @PreDestroy
    public void destroy() {
        System.out.println("this is destroy method2");
    }
}

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

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

package springTest2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("springTest2")
public class ConfigTest {
    @Bean
    Test2 test2() {
        return new Test2();
    }
}

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

再测试一下:

package springTest2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigTest.class);
                System.out.println("#################################");
        context.close();
    }
}

结果如下:

三、xml配置的方式:

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

package springTest2;
public class Test3 {
    public void init() {
        System.out.println("this is init method3");
    }
    public Test3() {
        super();
        System.out.println("构造函数3");
    }
    public void destroy() {
        System.out.println("this is destroy method3");
    }
    public void test() {
        System.out.println("testttttttt");
    }
}

不同的地方就在于,第一个例子中是使用注解告诉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">  

<bean id="initOrDestroyTest" class="springTest2.Test3" init-method="init" destroy-method="destroy">
</bean>
</beans>

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

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

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

package springTest2;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("spring.xml");
        System.out.println("#################################");
        context1.close();
    }
}

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

结果如下:

这里需要说明的一点是,在实际的web应用使用时,可以在web.xml中使用类似下边的配置来加载bean,实现init method:

<servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping> 

然后启动tomcat结果如下:



这里边没有调用destroy method,原因是spring本身代码就需要我们手动调用销毁bean的方法,像前边的几个例子中的context.close就是。

如果不手动调用这个方法,bean就不会被销毁,也就不会去调用destroy method,这也就是为何这里在web.xml中配置后,启动tomcat 只打印了构造函数和init方法中的内容。

例子都是很简单的,而通过简单的例子对比可能能更进一步理解相关的知识,理解了才能在实际应用中更好的进行选择和集成。

java代码中init method和destroy method的三种使用方式的更多相关文章

  1. spring bean的init 方法和 destory方法的三种实现方式

    1.通过@Bean(initMethod ="initPerson",destroyMethod ="destroyPerson" ) public class ...

  2. Java代码消除switch/case,if/else语句的几种实现方式

    转自:https://my.oschina.net/stefanzhlg/blog/372413 我们在平时的编码中,我们经常会遇到这样的情况: 使用过多的switch/case 或者 if else ...

  3. 面试题:JVM在Java堆中对对象的创建、内存结构、访问方式

    一.对象创建过程 1.检查类是否已被加载 JVM遇到new指令时,首先会去检查这个指令参数能否在常量池中定位到这个类的符号引用,检查这个符号引用代表的类是否已被加载.解析.初始化,若没有,则进行类加载 ...

  4. java高级用法之:在JNA中将本地方法映射到JAVA代码中

    目录 简介 Library Mapping Function Mapping Invocation Mapping 防止VM崩溃 性能考虑 总结 简介 不管是JNI还是JNA,最终调用的都是nativ ...

  5. Spring MVC框架下在java代码中访问applicationContext.xml文件中配置的文件(可以用于读取配置文件内容)

    <bean id="propertyConfigurer" class="com.****.framework.core.SpringPropertiesUtil& ...

  6. 使用mongo-java-driver3.0.2.jar和mongodb3.0在java代码中的用户验证4

    以下是使用mongo-java-driver3.0.2.jar和mongodb3.0.4在java代码中的用户验证: ServerAddress sa = new ServerAddress(host ...

  7. Android color(颜色) 在XML文件和java代码中

    Android color(颜色) 在XML文件和java代码中,有需要的朋友可以参考下. 1.使用Color类的常量,如: int color = Color.BLUE;//创建一个蓝色 是使用An ...

  8. 关于在Java代码中写Sql语句需要注意的问题

    最近做程序,时不时需要自己去手动将sql语句直接写入到Java代码中,写入sql语句时,需要注意几个小问题. 先看我之前写的几句简单的sql语句,自以为没有问题,但是编译直接报错. String st ...

  9. java代码中获取进程process id(转)

    另一方面,线程ID=进程ID+内部线程对象ID并不成立,    参考: blog.csdn.net/heyetina/article/details/6633901     如何在java代码中获取进 ...

随机推荐

  1. Sql Server的艺术(六) SQL 子查询,创建使用返回多行的子查询,子查询创建视图

    子查询或内部查询或嵌套查询在另一个SQL查询的查询和嵌入式WHERE子句中. 子查询用于返回将被用于在主查询作为条件的数据,以进一步限制要检索的数据. 子查询可以在SELECT,INSERT,UPDA ...

  2. [HTTP] PHP 实现 HTTP Server 原理

    单进程服务器简陋版: <?php /** * Single http server. * * Access http://127.0.0.1:8081 * * @license Apache-2 ...

  3. VUE脚手架搭建

    1.什么vue-cli    vue-cli是vue.js的脚手架,用于自动生成vue.js工程模板的. 步骤: 2.安装   ->全局安装   npm install vue-cli -g 或 ...

  4. VUE-node.js

    1.什么是node.js 它是可以运行javascript的服务平台        可以把它当做一门后端程序,只是它的开发语言是Javascript2.Python:自己创建的服务       php ...

  5. git修改最后一次commit的内容

    提交修改 $ git add test.txt $ git commit -m "提交test.txt文件" 修改注释说明 如果需要修改commit的注释说明,则执行以下命令: $ ...

  6. 05_Python Format Operation

    Python格式化输出 print('name: %s,version: %s,code: %d' %('Python',3.6,3)) print('name: {name},version: {v ...

  7. ABP官方文档翻译 3.8 数据过滤器

    数据过滤器 介绍 预定义过滤器 ISoftDelete 何时使用? IMustHaveTenant 何时使用? IMayHaveTenant 何时使用 禁用过滤器 关于using语句 关于多租户 全局 ...

  8. CentOS下mysql数据库data目录迁移和配置优化

    目录迁移 关闭数据库服务 service mysqld stop 复制数据库 mv /var/lib/mysql /data/mysql # 或者使用cp -a复制 # 这两个命令都会带权限到新目录去 ...

  9. react小结

    react基础小结 1. 例子 import React from 'react' import { render } from 'react-dom' // 定义组件 class Hello ext ...

  10. LeetCode - 654. Maximum Binary Tree

    Given an integer array with no duplicates. A maximum tree building on this array is defined as follo ...