栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring 注解驱动开发

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring 注解驱动开发

bean 的生命周期意思是指从 Bean 创建,到 Bean 初始化,再到销毁的过程
Spring IoC 容器管理 bean 的生命周期,我们可以自定义初始化和销毁方法,容器在 bean 进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。

一、@Bean 指定初始化和销毁方法 1.1 创建实体类 Car,在实体类中创建初始化方法以及销毁方法
package org.example.pojo;

public class Car {

    public Car(){
        System.out.println("car constructor...");
    }

    public void initCar(){
        System.out.println("car ... initCar...");
    }

    public void destroyCar(){
        System.out.println("car ... destroyCar");
    }
}

1.2 创建配置类,同时向容器中注入实体类 Car

在通过 @Bean 注解向容器中注入 Car 时,同时添加初始化和销毁方法。添加方法:在 @Bean 注解中新增 initMethod 和 destoryMethod
两个属性,用以指定需要添加的初始化和销毁方法。

package org.example.config;

import org.example.pojo.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InitAndDestoryTestConfig {
    @Scope
    @Bean(initMethod = "initCar", destroyMethod = "destroyCar")
    public Car car(){
        return new Car();
    }
}

1.3 测试方法
@Test
public void testInitAndDestroy(){
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(InitAndDestroyTestConfig.class);
    System.out.println("容器创建完成......");
    Object car = ac.getBean("car");
    Object car1 = ac.getBean("car");
    System.out.println(car);
    System.out.println(car1);
    System.out.println(car == car1);
    ac.close();
}

测试结果:

再来测一下当 Scope 为 多实例时的情况:
将配置类中 @Scope 的 value 属性修改为 ”prototype“,测试方法不变,进行测试,测试结果如下:

1.4 总结
单实例多实例
构造函数(对象创建)时间在容器启动的时候创建对象在每次获取的时候创建对象
初始化时间对象创建完成,并赋值好,调用初始化方法对象创建完成,并赋值好,调用初始化方法
销毁时间在容器关闭的时候调用销毁方法容器不会管理bean,故而容器不会调用销毁方法
二、InitializingBean 和 DisposableBean 2.1 接口定义 2.1.1 InitializingBean 接口定义
public interface InitializingBean {
	void afterPropertiesSet() throws Exception;
}

在容器对 bean 进行初始化时,如果该 bean 实现了InitializingBean 接口,将会调用接口中的 afterPropertiesSet() 方法,完成一些用户自定义的初始化操作。

2.1.2 DisposableBean 接口
public interface DisposableBean {
	void destroy() throws Exception;
}

BeanFactory 将在单实例 bean 销毁时调用 destroy 方法。

2.1.3 案例

实体类 Car 实现InitializingBean 和 DisposableBean 接口

package org.example.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class Car implements InitializingBean, DisposableBean {

    public Car(){
        System.out.println("car constructor...");
    }

    public void initCar(){
        System.out.println("car ... initCar...");
    }

    public void destroyCar(){
        System.out.println("car ... destroyCar");
    }

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

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("car......InitializingBean......afterPropertiesSet");
    }
}

配置类以及测试方法保持不变,测试结果如下:

2.1.4 总结

当一个实体类中既通过 @Bean 注解指定了 initMethod 以及 destroyMethod,还实现了 InitializingBean 和 DisposableBean 接口,那么容器在初始化时会优先执行 InitializingBean 中的 afterPropertiesSet() 方法,而在销毁阶段,DisposableBean 中的 destroy 方法的执行顺序也是优先于 @Bean 注解指定的销毁方法的。

三、使用 JSR250 3.1 @PostConstruct 注解
@documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

标有 @PostConstruct 注解的方法,容器在 bean 创建完成并且属性赋值完成后,会调用该初始化方法。

3.2 @PreDestroy 注解
@documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

标有 @PreDestroy 注解的方法,会在容器销毁 bean 之前进行调用

3.3 案例

修改实体类 Car:

package org.example.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class Car implements InitializingBean, DisposableBean {

    public Car(){
        System.out.println("car constructor...");
    }

    public void initCar(){
        System.out.println("car ... initCar...");
    }

    public void destoryCar(){
        System.out.println("car ... destoryCar");
    }

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

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("car......InitializingBean......afterPropertiesSet");
    }

    @PostConstruct
    public void initPostConstruct(){
        System.out.println("car......initPostConstruct......");
    }

    @PreDestroy
    public void initPreDestroy(){
        System.out.println("car......initPreDestroy......");
    }
}

配置类以及测试方法不变,测试结果:

可以看出带有 @PostConstruct 注解和@PreDestroy 注解的方法其执行顺序要优先于其他两种方式。

四、使用 BeanPostProcessor 接口 4.1 接口介绍

BeanPostProcessor 是一个接口,它是 bean 的后置处理器,该接口会在 bean 初始化前后进行一些处理工作。

接口源码:

public interface BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

postProcessBeforeInitialization 方法:在初始化之前工作postProcessAfterInitialization:在初始化之后工作方法参数 bean:bean 实例方法参数 beanName:bean 实例的名称返回值:返回值为原始的 bean 实例或者经过包装后的 bean 实例,如果返回值为 null,后续的 BeanPostProcessor 将不会被执行。 4.2 案例

创建 MyBeanPostProcessor 类,实现 BeanPostProcessor 接口,同时将 MyBeanPostProcessor 类通过 @Component 注解注入到容器中。

package org.example.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..." + beanName + "--->" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..." + beanName + "--->" + bean);
        return bean;
    }
}

配置类 InitAndDestoryTestConfig 添加注解 @ComponentScan(“org.example.processor”),将 MyBeanPostProcessor 同过包扫描的方式注入到容器中。

package org.example.config;

import org.example.pojo.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("org.example.processor")
public class InitAndDestoryTestConfig {
    @Bean(initMethod = "initCar", destroyMethod = "destoryCar")
    public Car car(){
        return new Car();
    }
}

测试方法不变,测试结果如下:

4.3 总结

BeanPostProcessor 中的 postProcessBeforeInitialization 方法执行时间要先于其他三种方式,但是 postProcessAfterInitialization 方法与其他三种销毁方法是不一样的,该方法是在 bean 初始化完成之后执行,并不属于销毁方法。

五、总结

本节内容总共介绍了四种初始化方法,以及三种销毁方法,另外 BeanPostProcessor 中的 postProcessAfterInitialization 并不属于销毁方法,该方法是在 bean 初始化完成之后执行的。
四种初始化方法的执行时间优先顺序如下:
BeanPostProcessor 中的 postProcessBeforeInitialization > @PostConstruct 注解 > InitializingBean 接口中的 afterPropertiesSet 方法 > @Bean 注解中 initMethod 属性指定的初始化方法

三种销毁方法的执行时间优先顺序如下:
@PreDestroy 注解 > DisposableBean 接口中的 destroy 方法 > @Bean 注解中 destroyMethod 属性指定的初始化方法

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781652.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号