指定bean的初始化和销毁的四种方法

2018-07-09  本文已影响0人  缓慢移动的蜗牛

所使用的spring的版本为:4.3.12.RELEASE

一、使用@Bean时,指定initMethod和destroyMethod

package com.nanc.config;

import com.nanc.entity.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({"com.nanc.entity"})
@PropertySource(value = {"classpath:/person.properties"})
public class MainConfig {
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}

实体类

package com.nanc.entity;

import java.io.Serializable;

public class Car implements Serializable {
   private static final long serialVersionUID = 7710625002326921548L;

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

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

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

person.properties文件

person.nickName=张三疯

二、让Bean实现InitializingBean(定义初始化逻辑)、DisposableBean(定义销毁逻辑)接口

实体bean的代码,采用注解的方式

package com.nanc.entity;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import java.io.Serializable;

@Component
public class Cat implements Serializable, InitializingBean, DisposableBean {
   private static final long serialVersionUID = -7379286171731060156L;

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

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

三、使用JSR250规范,@PostConstruct、@PreDestroy

@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作

实体类

package com.nanc.entity;

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.Serializable;

@Component
public class Dog implements Serializable {
   private static final long serialVersionUID = 316697758215346823L;

   public Dog() {
      System.out.println("dog constructor...");
   }


   //对象创建并赋值之后调用
   @PostConstruct
   public void init(){
      System.out.println("dog  @PostConstruct....");
   }

   //容器移除对象之前
   @PreDestroy
   public void destroy(){
      System.out.println("dog   @PreDestroy...");
   }
}

四、使用BeanPostProcessor接口(bean的后置处理器)

在bean初始化前后进行一些处理工作;

postProcessBeforeInitialization:在初始化之前工作

postProcessAfterInitialization:在初始化之后工作

package com.nanc.entity;

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;
   }
}

BeanPostProcessor在spring中的应用举例

向一个bean中注入ApplicationContext

package com.nanc.entity;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

@Component
public class User implements ApplicationContextAware,EmbeddedValueResolverAware {
    private ApplicationContext applicationContext;
    private StringValueResolver resolver;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
        System.out.println("解析的值为:"+resolver.resolveStringValue("${person.nickName}"));
    }
}

注入ApplicationContext,StringValueResolver的原因?

通过打断点可以,在spring的初始化流程中,调用了ApplicationContextAwareProcessor类中的postProcessBeforeInitialization(final Object bean, String beanName)方法

下面是相关的两个方法

@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
   AccessControlContext acc = null;

   if (System.getSecurityManager() != null &&
         (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
               bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
               bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
      acc = this.applicationContext.getBeanFactory().getAccessControlContext();
   }

   if (acc != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
         @Override
         public Object run() {
            invokeAwareInterfaces(bean);
            return null;
         }
      }, acc);
   }
   else {
      invokeAwareInterfaces(bean);
   }

   return bean;
}




private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

测试代码

@Test
public void test(){
   ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

   Person person = applicationContext.getBean(Person.class);

   System.out.println(person);
}

说明:可以在User类中的第16或22行打上断点,查看具体的调用栈信息

pom文件中的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.12.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.3.12.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.3.12.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>
上一篇下一篇

猜你喜欢

热点阅读