spring中关于bean的生命周期的常用注解

singleton的,非lazy的bean,在IOC容器初始化的时候就被加载了,像基本的servlet有生命周期一样,spring的bean,也是有生命周期的。这也是spring的bean与java中的class不一样的地方,它远比class丰富。

今天,我们就介绍与spring的bean的lifeCycle有关的几个注解。


preparation:

我们有个Customer.java(package com.ocean.bean),
CustomerService.java(package com.ocean.service),
MainConfig(package com.ocean.config),
以及一个测试类SpringTest.java(package com.ocean.test)。

配置类很简单,主要提供了包的自动扫描:

package com.ocean.config;

import com.ocean.service.CustomerService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan("com.ocean")
@Configuration
public class MainConfig {

//    @Bean(initMethod = "customInitBean",destroyMethod = "customDestroyBean")
//    public CustomerService customerService(){
//        return new CustomerService();
//    }

}

Customer这个bean给它注入个属性值“Jack”:

package com.ocean.bean;


import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

@Component
public class Customer{

    @Value("Jack")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


}

然后是CustomerService类,我们主要考察这个类的生命周期。

我们在里面放入Customer并自动注入,因为我们需要观察属性注入的时机。

    @Autowired
    private Customer customer;

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;

    }

    public CustomerService() {
        System.out.println("CustomerService's empty constructor...");
    }

我们的预期是先调用构造方法,因为没有类的实例什么都做不了,所以构造器的日志一定会打印。但是,我们不知道属性是什么时候有值的。

我们接下来自定义初始化方法和销毁方法:

        public void customInitBean(){
        System.out.println("CustomerService's customInitBean...");
    }

    public void customDestroyBean(){
        System.out.println("CustomerService's customDestroyBean...");
    }

为了让这两个自定义方法生效,我们要用@Bean的方式为spring容器注册CustomerService:

 @Bean(initMethod = "customInitBean",destroyMethod = "customDestroyBean")
    public CustomerService customerService(){
        return new CustomerService();
    }

我的测试类:

package com.ocean.test;

import com.ocean.config.MainConfig;
import com.ocean.service.CustomerService;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class SpringTest {

    @Test
    public void test01() {
        AbstractApplicationContext applicationContext
                = new AnnotationConfigApplicationContext(MainConfig.class);

        System.out.println("Context has been initialized..");

//        CustomerService customerService = applicationContext.getBean(CustomerService.class);

//        System.out.println("Already retrieved bean from context,next,show the bean data");
//
//
//        System.out.println(customerService.getCustomer().getName());
        applicationContext.close();
    }
}


一切都很好。

现在我们就不再用自定义的初始化和销毁方法了,因为这样太麻烦了,而且spring和javax给了我们方便的接口和注解。


把配置类中通过@Bean方式注册bean的代码注掉。

把CustomerService中自定义的初始化和销毁方法删掉。

因为我们要观测属性注入的时机,我们要提供一个有参构造。

然后,我们使用

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

注解标注初始化方法,

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

标注销毁方法。


    @Autowired
    private Customer customer;

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;

    }

    public CustomerService(Customer customer) {
        this.customer = customer;
        System.out.println("CustomerService's constructor...");
        System.out.println("Property set:" + customer);
    }

    @PostConstruct
    public void postContruct(){
        System.out.println("postContruct() performs some initialization after all the setter methods have been called");
    }

    @PreDestroy
    public void predestroy(){
        System.out.println("predestroy() the method that's called back before bean is destroyed");
    }

来看一下此时的结果:


实例化–>属性注入–>初始化–>销毁,这就是我们的lifeCycle了。


另一种初始化和销毁的方式是通过两个接口:

public class CustomerService  implements InitializingBean ,DisposableBean

我们实现里面的抽象方法:

 @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("CustomerService's afterPropertiesSet...");
    }

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

从名字就可以直观的看出,一个的作用时机是属性设置好之后,另一个的时机是销毁的时候。

我们再走一边测试:


这也是没有问题的。

在测试类中,当我们拿到了bean对象,我们也可以去取出里面的值:

 AbstractApplicationContext applicationContext
                = new AnnotationConfigApplicationContext(MainConfig.class);

        System.out.println("Context has been initialized..");

        CustomerService customerService = applicationContext.getBean(CustomerService.class);

        System.out.println("Already retrieved bean from context,next,show the bean data");

        System.out.println(customerService.getCustomer().getName());

        applicationContext.close();


与bean的生命周期息息相关的,还有一个在spring中常用的处理器,叫做BeanPostProcessor。

我们手动写一个后置处理器,spring会自动探测到。

package com.ocean.bean;

import com.ocean.service.CustomerService;
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 o, String s) throws BeansException {
        System.out.println("postProcessBeforeInitialization:" + s + "-->" + o);
        return o;
    }

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

我们想知道postProcessBeforeInitialization,postProcessAfterInitialization这两个方法出现的时机。


spring自己的bean都探测到了我们自定义的后置处理器,这说明在bean的生命周期中,后置处理器是躲不开的一环。

我们看看我们自己写的bean:


后置处理器中两个方法的时机就是在初始化前后。


关于后置处理器,以后肯定还会深入,但我们先debug一下看看他们的存在吧。

在加载spring自己bean的时候,我们有看到大量的后置处理器:


有一个是我们写的。

其他的,各有用途,比如解析@Resource注解的,就是CommonAnnotationBeanPostProcessor,
解析@Autowired注解的,就是AutowiredAnnotationBeanPostProcessor。

再看一下后置处理器中两个方法出现的时机:

在利用反射invoke初始化方法的前后,分别调用了
postProcessBeforeInitialization,postProcessAfterInitialization。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring有多种方式来定义和管理bean的生命周期。其包括使用XML配置、注解和使用JSR250的@PostConstruct和@PreDestroy注解。 1. XML配置方式:在XML配置文件,可以使用<bean>标签来定义bean,并通过指定init-method和destroy-method属性来指定bean的初始化和销毁方法。例如: ```xml <bean id="user" class="com.demo.pojo.User" init-method="init" destroy-method="destroy"> </bean> ``` 在这个例子,init-method属性指定了bean的初始化方法为"init",destroy-method属性指定了bean的销毁方法为"destroy"。 2. 注解方式:使用注解可以更简洁地定义bean的生命周期。可以使用注解@Bean来标注一个方法,该方法返回一个bean实例,并可以使用@PostConstruct和@PreDestroy注解来指定初始化和销毁方法。例如: ```java @Configuration public class AppConfig { @Bean(initMethod = "init", destroyMethod = "destroy") public User user() { return new User(); } } ``` 在这个例子,@Bean注解标注的方法user()返回一个User实例,并通过initMethod和destroyMethod属性指定了初始化和销毁方法。 3. 使用JSR250的@PostConstruct和@PreDestroy注解:可以在bean类使用@PostConstruct和@PreDestroy注解来标注初始化和销毁方法。例如: ```java public class User { @PostConstruct public void init() { // 初始化方法的逻辑 } @PreDestroy public void destroy() { // 销毁方法的逻辑 } } ``` 在这个例子,@PostConstruct注解标注的方法init()会在bean初始化之后调用,@PreDestroy注解标注的方法destroy()会在bean销毁之前调用。 总结起来,Spring提供了多种方式来定义和管理bean的生命周期,包括XML配置、注解和使用JSR250的@PostConstruct和@PreDestroy注解。这些方式可以根据具体的需求和项目的特点来选择和使用。[1][2][3]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值