zoukankan      html  css  js  c++  java
  • spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入

    spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入
    spring中InitializingBean接口使用理解
     
    关于在spring  容器初始化 bean 和销毁前所做的操作定义方式有三种:

    第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作

    第二种是:通过在xml中定义init-method 和destory-method方法

    第三种是:通过bean实现InitializingBean和 DisposableBean接口

    例如:TransactionTemplate实现InitializingBean接口,主要是判断transactionManager是否已经初始化,如果没有则抛出异常。源码如下:
    public void afterPropertiesSet() {
            if (this.transactionManager == null) {
                throw new IllegalArgumentException("Property 'transactionManager' is required");
            }
    }

    目前我知道的有:在xml中定义的时候用init-method和destory-method,还有一种就是定义bean的时候实现DisposableBean和InitializingBean 这两个接口,打开InitializingBean 的源码:

    public interface InitializingBean {
    
        /**
         * Invoked by a BeanFactory after it has set all bean properties supplied
         * (and satisfied BeanFactoryAware and ApplicationContextAware).
         * <p>This method allows the bean instance to perform initialization only
         * possible when all bean properties have been set and to throw an
         * exception in the event of misconfiguration.
         * @throws Exception in the event of misconfiguration (such
         * as failure to set an essential property) or if initialization fails.
         */
        void afterPropertiesSet() throws Exception;
    
    }

    根据注解很清楚的可以看出,afterPropertiesSet()表示在资源加载完以后,初始化bean之前执行的方法,我猜想spring底层应该会在初始化bean的时候,应该会使用(bean instanceof InitializingBean)判断是不是实现了这个接口,其实在很多框架中都是这么干的,但是因为没研究过spring源码,暂且还不知道底层原理。这样我们就可以在初始化的时候,做一些自己想要做的事了。
    同理,DisposableBean就是在一个bean被销毁的时候,spring容器会帮你自动执行这个方法,估计底层原理也是差不多的,对于一些使用完之后需要释放资源的bean,我们都会实现这个接口,或者是配置destory-method方法。源码也基本是相似的,只是把afterPropertiesSet改为destroy。

    public interface DisposableBean {
    
        /**
         * Invoked by a BeanFactory on destruction of a singleton.
         * @throws Exception in case of shutdown errors.
         * Exceptions will get logged but not rethrown to allow
         * other beans to release their resources too.
         */
        void destroy() throws Exception;
    
    }

    ApplicationContextAware
      其实我们看到---Aware就知道是干嘛用的了,就是属性注入的,但是这个ApplicationContextAware的不同地方在于,实现了这个接口的bean,当spring容器初始化的时候,会自动的将ApplicationContext注入进来:

    import org.apache.commons.lang.Validate;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;
    /**
     * applicationContext静态化
     * 使用了ApplicationContextAware接口的类,如果受spring容器管理的
     * 话,那么就会自动的调用ApplicationContextAware中的setApplicationContext方法
     * @author Hotusm
     *
     */
    @Service
    @Lazy(false)
    public class SpringContextHolder implements ApplicationContextAware,DisposableBean{
        
        private static ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext)
                throws BeansException {
            
            SpringContextHolder.applicationContext=applicationContext;
        }
        //清空applicationContext 设置其为null
        @Override
        public void destroy() throws Exception {
            SpringContextHolder.clearHolder();
        }
        //获得applicationContext
        public static ApplicationContext getApplicationContext() {
            //assertContextInjected();
            return applicationContext;
        }
        
        public static void clearHolder(){
            applicationContext=null;
        }
        //获取Bean
        public static <T> T getBean(Class<T> requiredType){
            //assertContextInjected();
            return (T) getApplicationContext().getBean(requiredType);
        }
        @SuppressWarnings("unchecked")
        public static <T> T getBean(String name){
            assertContextInjected();
            return (T) getApplicationContext().getBean(name);
        }
        //判断application是否为空
        public static void assertContextInjected(){
            Validate.isTrue(applicationContext==null, "application未注入 ,请在springContext.xml中注入SpringHolder!");
        }
        
    }

    因为我们在做开发的时候,并不是说在每一个地方都能将属性注入到我们想要的地方去的,比如在Utils使用到dao,我们就不能直接注入了,这个时候就是我们需要封装springContext的时候了,而ApplicationContextAware就起了关键性的作用。

     
  • 相关阅读:
    Win10 x64 + CUDA 10.0 + cuDNN v7.5 + TensorFlow GPU 1.13 安装指南
    工作十一年总结
    Anaconda3 指南
    Win Linux 双系统安装指南
    OBS 录制视频 自己留存
    React Starter Kit 中文文档
    .NET Framework 系统版本支持表
    Hyper-V和其他虚拟机共存 【转】
    Docker入门03——Container
    Docker入门02——Dockerfile详解
  • 原文地址:https://www.cnblogs.com/duanxz/p/4537195.html
Copyright © 2011-2022 走看看