美文网首页
指定bean的初始化和销毁的四种方法

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

作者: 缓慢移动的蜗牛 | 来源:发表于2018-07-09 11:45 被阅读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>
    

    相关文章

      网友评论

          本文标题:指定bean的初始化和销毁的四种方法

          本文链接:https://www.haomeiwen.com/subject/evvzuftx.html