• Spring可二次开发常用接口、类及其源码详解


      Spring为了用户的开发方便和特性支持,开放了一些特殊接口和类,用户可进行实现或者继承,常见的如这些: ApplicationContextAware接口、ApplicationEvent抽象类、ApplicationListener接口、BeanNameAware接口、BeanFactoryAware接口、InitializingBean接口、DisposableBean接口、BeanPostProcessor接口。 

    一、ApplicationContextAware接口

      AbstractApplicationContext类是Spring容器应用上下文的一个抽象父类,ApplicationContextAware是用来获取spring的上下文。当一个类需要获取ApplicationContext实例时,可以通过工具类直接实现ApplicationContextAware接口,返回ApplicationContext对象。如下代码所示:

       @Component
        public class BeansUtils implements ApplicationContextAware {
    
            private static ApplicationContext context;
    
            public static <T> T getBean(Class<T> bean) {
                return context.getBean(bean);
            }
            public static <T> T getBean(String var1, @Nullable Class<T> var2){
                return context.getBean(var1, var2);
            }
    
            public static ApplicationContext getContext() {
                return context;
            }
    
            @Override
            public void setApplicationContext(ApplicationContext context) throws BeansException {
                BeansUtils.context = context;
            }
        }

      以上一段代码就可使获取ApplicationContext以及某些Bean,那么其原理是什么呢?

      我们在初始化的时候,从入口类ClassPathXmlApplicationContext->AbstractApplicationContext类的的refresh方法 ->prepareBeanFactory方法:

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 设置 BeanFactory 的类加载器,我们知道 BeanFactory 需要加载类,也就需要类加载器,这里设置为当前 ApplicationContext 的类加载器
            beanFactory.setBeanClassLoader(getClassLoader());
             // 设置 BeanExpressionResolver
            beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
            beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    // 添加一个 BeanPostProcessor,这个 processor 比较简单,实现了 Aware 接口的几个特殊的 beans 在初始化的时候,这个 processor 负责回调
            beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
             // 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,Spring 会通过其他方式来处理这些依赖。
            beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
            beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
            beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
            beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
            beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
            beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
            beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
            beanFactory.registerResolvableDependency(ResourceLoader.class, this);
            beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
            beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    
            if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
                beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
                beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
            }// 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
            if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
                beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
            }
             // 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
            if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
                beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
            }
             // 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
            if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
                beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
            }
        }

      beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); spring源码里面将ApplicationContextAwareProcessor加入到BeanPostProcessor处理器里面了,并且传的是一个ApplicationContext类型参数进去。

    class ApplicationContextAwareProcessor implements BeanPostProcessor {
    
        private final ConfigurableApplicationContext applicationContext;
    //beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));调用此构造方法把ApplicationContext传过来 public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; } //实例化之前进行的处理 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>() { public Object run() { //给Aware的实现类set值进去 invokeAwareInterfaces(bean); return null; } }, acc); } else { //给Aware的实现类set值进去 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( new EmbeddedValueResolver(this.applicationContext.getBeanFactory())); } 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); } //判读是否是属于ApplicationContextAware接口的类 if (bean instanceof ApplicationContextAware) { //调用实现类的setApplicationContext方法把applicationContext set进去 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }   // ... ... }

      BeanPostProcessor处理器,可以在bean初始化前、后根据自己业务做一些事情。postProcessBeforeInitialization方法里面,里面invokeAwareInterfaces方法是怎样都会走的,里面有这样一段代码((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);这就是去调用具体实现类的setApplicationContext方法把applicationContext传进去了。其他Aware基本上也是这个道理。

      可以很清楚的了解到ApplicationContextAware实现类在应用启动的时候就会初始化。

    二、ApplicationEvent抽象类、ApplicationListener接口

      1、使用测试

      ApplicationEvent抽象类、ApplicationListener接口是常常搭配使用的:

    • ApplicationEvent:是个抽象类,里面只有一个构造函数和一个长整型的timestamp。
    • ApplicationListener:是一个接口,里面只有一个onApplicationEvent方法。所以自己的类在实现该接口的时候,要实装该方法。
    • ApplicationContext:如果在上下文中部署一个实现了ApplicationListener接口的bean,那么每当在一个ApplicationEvent发布到 ApplicationContext时,这个bean得到通知。

      因此ApplicationEvent、ApplicationListener、ApplicationContext三者其实这就是标准的Oberver设计模式。如下面一个例子:

    public class EmailEvent extends ApplicationEvent {
    
        private static final long serialVersionUID = 1L;
        public String address;  
        public String text;
        
        public EmailEvent(Object source) {
            super(source);
        }
        
        public EmailEvent(Object source, String address, String text) {
            super(source);
            this.address = address;
            this.text = text;
        }
        
        public void print(){
            System.out.println("hello spring event!");
        }
    }
    
    public class EmailListener implements ApplicationListener {
    
        public void onApplicationEvent(ApplicationEvent  event) {
            if(event instanceof EmailEvent){
                EmailEvent emailEvent = (EmailEvent)event;
                emailEvent.print();
                System.out.println("the source is:"+emailEvent.getSource());
                System.out.println("the address is:"+emailEvent.address);
                System.out.println("the email's context is:"+emailEvent.text);
            }
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
            EmailEvent event = new EmailEvent("hello","boylmx@163.com","this is a email text!");
            context.publishEvent(event);
        }
    }

      测试结果如下:

    hello spring event!  
    the source is:hello  
    the address is:boylmx@163.com  
    the email's context is:this is a email text! 

      这就是一个基于ApplicationEvent、ApplicationListener使用的例子,实现Spring事件机制主要有4个类:

    • ApplicationEvent:事件,每个实现类表示一类事件,可携带数据。
    • ApplicationListener:事件监听器,用于接收事件处理时间。
    • ApplicationEventMulticaster:事件管理者,用于事件监听器的注册和事件的广播。
    • ApplicationEventPublisher:事件发布者,委托ApplicationEventMulticaster完成事件发布。

      那我们来进行源码解析。

      2、ApplicationEvent

      ApplicationEvent表示事件,每个实现类表示一类事件,可携带数据。下面以一些Spring提供的标准事件,都继承了ApplicationEvent。

    事件 描述
    ContextRefreshedEvent 事件发布在ApplicationContext初始化或刷新时(例如,通过在ConfigurableApplicationContext接口使用refresh()方法)。这里,“初始化”意味着所有bean加载,post-processor bean被检测到并且激活,单例预先实例化,ApplicationContext对象可以使用了。只要上下文没有关闭,可以触发多次刷新,ApplicationContext提供了一种可选择的支持这种“热”刷新。例如XmlWebApplicationContext支持热刷新,但GenericApplicationContext并非如此。具体是在AbstractApplicationContext的finishRefresh()方法中。
    ContextRefreshedEvent

    事件发布在ApplicationContext初始化或刷新时(例如,通过在ConfigurableApplicationContext接口使用refresh()方法)。这里,“初始化”意味着所有bean加载,post-processor bean被检测到并且激活,单例预先实例化,ApplicationContext对象可以使用了。只要上下文没有关闭,可以触发多次刷新,ApplicationContext提供了一种可选择的支持这种“热”刷新。例如,XmlWebApplicationContext支持热刷新,但GenericApplicationContext并非如此。具体是在AbstractApplicationContext的finishRefresh()方法中。

    ContextStartedEvent 事件发布在ApplicationContext开始使用ConfigurableApplicationContext接口start()方法。这里,“开始”意味着所有生命周期bean接收到一个明确的起始信号。通常,这个信号用于明确停止后重新启动,但它也可以用于启动组件没有被配置为自动运行(例如,组件还没有开始初始化)。
    ContextStoppedEvent 事件发布在ApplicationContext停止时通过使用ConfigurableApplicationContext接口上的stop()方法。在这里,“停止”意味着所有生命周期bean接收一个显式的停止信号。停止上下文可以通过重新调用start()方法。
    ContextClosedEvent 事件发布在ApplicationContext关闭时通过关闭ConfigurableApplicationContext接口方法。这里,“封闭”意味着所有单例bean被摧毁。一个封闭的环境达到生命的终结。它不能刷新或重启。
    RequestHandledEvent 一个特定的web事件告诉所有能处理HTTP请求的bean 。这个事件是在请求完成后发布的。这个事件只适用于使用Spring的DispatcherServlet的web应用程序。

      ApplicationEvent代码如下:

    public abstract class ApplicationEvent extends EventObject {
        private static final long serialVersionUID = 7099057708183571937L;
        private final long timestamp = System.currentTimeMillis();
    
        public ApplicationEvent(Object source) {
            super(source);
        }
    
        public final long getTimestamp() {
            return this.timestamp;
        }
    }

      3、ApplicationListener

    @FunctionalInterface
    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
       void onApplicationEvent(E event);
    }

      当事件监听器接收到它可以处理的事件,会调用onApplicationEvent()方法。注意到ApplicationListener是泛型参数,这样可以实现所有继承了ApplicationEvent的监听。我们可以尽可能多的注册想要的事件侦听器,但是默认情况下事件监听器同步接收事件。这意味着publishEvent()方法会阻塞直到所有的事件监听器成处理完事件。这种单线程同步方法的一个特点是,当一个监听器接收到一个事件时,它运行在事务上下文的发布者线程上(如果事务上下文可用)。如果事件的发布需要另一种策略(譬如多线程)需要实现自己的 ApplicationEventMulticaster接口类。

      4、ApplicationEventMulticaster

      ApplicationEventMulticaster接口方法分为三类,注册事件监听器、移除事件监听器、发布事件。

    public interface ApplicationEventMulticaster {
       void addApplicationListener(ApplicationListener<?> listener);
       void addApplicationListenerBean(String listenerBeanName);
       void removeApplicationListener(ApplicationListener<?> listener);
       void removeApplicationListenerBean(String listenerBeanName);
       void removeAllListeners();
       void multicastEvent(ApplicationEvent event);
       void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
    }

      执行AbstractApplicationContext.initApplicationEventMulticaster() 方法时会实例化一个bean name为applicationEventMulticaster的SimpleApplicationEventMulticaster,它的父类实现了前5个方法依靠一个内部类ListenerRetriever维护了一个Set<ApplicationListener<?>>,本质事件监听器的注册或移除就是对这个Set的添加和移除操作。

    public abstract class AbstractApplicationEventMulticaster
          implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
       private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
       
       @Override
       public void addApplicationListener(ApplicationListener<?> listener) {
          synchronized (this.retrievalMutex) {
             // 如果已经注册,则显式删除代理的目标,以避免对同一个侦听器进行双重调用。
             Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
             if (singletonTarget instanceof ApplicationListener) {
                this.defaultRetriever.applicationListeners.remove(singletonTarget);
             }
             this.defaultRetriever.applicationListeners.add(listener);
             this.retrieverCache.clear();
          }
       }
     
       @Override
       public void removeApplicationListener(ApplicationListener<?> listener) {
          synchronized (this.retrievalMutex) {
             this.defaultRetriever.applicationListeners.remove(listener);
             this.retrieverCache.clear();
          }
       }
     
       private class ListenerRetriever {
          public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
          public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
          private final boolean preFiltered;
          public ListenerRetriever(boolean preFiltered) {
             this.preFiltered = preFiltered;
          }
          public Collection<ApplicationListener<?>> getApplicationListeners() {
             List<ApplicationListener<?>> allListeners = new ArrayList<>(
                   this.applicationListeners.size() + this.applicationListenerBeans.size());
             allListeners.addAll(this.applicationListeners);
             if (!this.applicationListenerBeans.isEmpty()) {
                BeanFactory beanFactory = getBeanFactory();
                for (String listenerBeanName : this.applicationListenerBeans) {
                   try {
                      ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                      if (this.preFiltered || !allListeners.contains(listener)) {
                         allListeners.add(listener);
                      }
                   }
                   catch (NoSuchBeanDefinitionException ex) {
                      // Singleton listener instance (without backing bean definition) disappeared -
                      // probably in the middle of the destruction phase
                   }
                }
             }
             if (!this.preFiltered || !this.applicationListenerBeans.isEmpty()) {
                AnnotationAwareOrderComparator.sort(allListeners);
             }
             return allListeners;
          }
       }
    }

      接口后两个方法由子类实现,可以看到SimpleApplicationEventMulticaster拥有一个Executor和ErrorHandler,分表表示监听器的调用线程池(如果不想使用单线程同步处理则可以设置一个线程池)和监听器处理事件失败的处理者(如果设置了的话)否则抛异常。 

    public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
       @Nullable
       private Executor taskExecutor;
       @Nullable
       private ErrorHandler errorHandler;
       public SimpleApplicationEventMulticaster() {
       }
       public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
          setBeanFactory(beanFactory);
       }
       public void setTaskExecutor(@Nullable Executor taskExecutor) {
          this.taskExecutor = taskExecutor;
       }
       public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
          this.errorHandler = errorHandler;
       }
       @Override
       public void multicastEvent(ApplicationEvent event) {
          //广播事件,可以自动分析出ApplicationEvent是那种事件类型
          multicastEvent(event, resolveDefaultEventType(event));
       }
       @Override
       public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
          ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
          //调用父类方法getApplicationListeners只取得能处理此类事件的时间监听器,依次处理
          for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
             Executor executor = getTaskExecutor();
             if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
             }
             else {
                invokeListener(listener, event);
             }
          }
       }
     
       private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
          return ResolvableType.forInstance(event);
       }
     
       protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
          ErrorHandler errorHandler = getErrorHandler();
          if (errorHandler != null) {
             try {
                doInvokeListener(listener, event);
             }
             catch (Throwable err) {
                errorHandler.handleError(err);
             }
          }
          else {
             doInvokeListener(listener, event);
          }
       }
     
       @SuppressWarnings({"unchecked", "rawtypes"})
       private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
          try {
             listener.onApplicationEvent(event);
          }
          catch (ClassCastException ex) {  // 省略}
       }
     
       private boolean matchesClassCastMessage(String classCastMessage, Class<?> eventClass) {// 省略}
    }

      5、ApplicationEventPublisher

    @FunctionalInterface
    public interface ApplicationEventPublisher {
       default void publishEvent(ApplicationEvent event) {
          publishEvent((Object) event);
       }
       void publishEvent(Object event);
    }

      ApplicationEventPublisher很简单只有两个发布事件的方法,AbstractApplicationContext是它的默认实现类,下面是具体实现。

    @Override
    public void publishEvent(ApplicationEvent event) {
       publishEvent(event, null);
    }
    @Override
    public void publishEvent(Object event) {
       publishEvent(event, null);
    }
    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
       Assert.notNull(event, "Event must not be null");
     
       ApplicationEvent applicationEvent;
       if (event instanceof ApplicationEvent) {
          applicationEvent = (ApplicationEvent) event;
       }
       else {
          applicationEvent = new PayloadApplicationEvent<>(this, event);
          if (eventType == null) {
             eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
          }
       }
     
       // Multicast right now if possible - or lazily once the multicaster is initialized
       if (this.earlyApplicationEvents != null) {
          this.earlyApplicationEvents.add(applicationEvent);
       }
       else {
          getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
       }
     
       // Publish event via parent context as well...
       if (this.parent != null) {
          if (this.parent instanceof AbstractApplicationContext) {
             ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
          }
          else {
             this.parent.publishEvent(event);
          }
       }
    }

      可以看到事件的发布依赖于前面提到的bean name是applicationEventMulticaster的SimpleApplicationEventMulticaster。关于监听器注册有两种方法:接口实现、注解,代码如下:

    //  使用接口实现方式
    public class RegisterListener implements ApplicationListener<UserRegisterEvent> {
        @Override
        public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {//../省略逻辑
        }
    }
    
    //  使用@EventListener注解方式
    @Component
    public class AnnotationRegisterListener {
        @EventListener
        public void register(UserRegisterEvent userRegisterEvent)
        {
        //../省略逻辑
        }
    }

    三、InitializingBean接口

      当需要在bean的全部属性设置成功后做些特殊的处理,可以让该bean实现InitializingBean接口。效果等同于bean的init-method属性的使用或者@PostContsuct注解的使用,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。

      测试代码如下:

    public class TestInitializingBean implements InitializingBean{
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("ceshi InitializingBean");        
        }
        public void testInit(){
            System.out.println("ceshi init-method");        
        }
    }

      配置文件如下:

    <bean id="testInitializingBean" class="com.TestInitializingBean" ></bean>

      Main函数如下:

    public class Main {
        public static void main(String[] args){
            ApplicationContext context = new FileSystemXmlApplicationContext("/src/main/java/com/beans.xml");
        }
    }

      测试结果为:

    ceshi InitializingBean

      这说明在spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法。那么在配置bean的时候使用init-method配置也可以为bean配置初始化方法,那这两个哪个会先执行呢,接下来测试一下,修改配置文件,加上init-method:

    <bean id="testInitializingBean" class="com.TestInitializingBean" init-method="testInit"></bean>

      运行程序,得出结果:

    ceshi InitializingBean
    ceshi init-method

      从结果可以看出,在Spring初始化bean的时候,如果该bean实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertieSet()方法,然后再调用init-method中指定的方法。

      那么这种方式在spring中是怎么实现的呢,通过查看Spring加载bean的源码类AbstractAutowiredCapableBeanFactory可以看出其中的奥妙,AbstractAutowiredCapableBeanFactory类中的invokeInitMethods说的非常清楚,如下:

    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
        //判断该bean是否实现了实现了InitializingBean接口,如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法
        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
             
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        public Object run() throws Exception {
                            //直接调用afterPropertiesSet
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    },getAccessControlContext());
                } catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }                
            else {
                //直接调用afterPropertiesSet
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }
        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();
            //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                //进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

      总结:

    • 注解、InitializingBean、init-method三种方式的执行顺序是:先注解,然后执行InitializingBean接口中定义的方法,最后执行init-method属性指定的方法。
    • Spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中通过init-method指定,两种方式可以同时使用。
    • 实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率要高一点,但是init-method方式消除了对spring的依赖。
    • 如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。

    四、DisposableBean接口

      同InitializingBean原理类似,当需要在bean销毁之前做些特殊的处理,可以让该bean实现DisposableBean接口,该接口也只定义了一个destory方法。效果等同于bean的destroy-method属性的使用或者@PreDestory注解的使用。

      注解、DisposableBean、destroy-method三种方式的执行顺序:先注解,然后执行DisposableBean接口中定义的方法,最后执行destroy-method属性指定的方法。

    五、BeanNameAware接口、BeanFactoryAware接口

      Bean都是“无知觉”的,就像黑客帝国中机械工厂里面“养殖”的人类,他们虽然能完成一定的功能,但是根本不知道自己在工厂(BeanFactory)中的代号(id),或者自己是在哪个工厂(BeanFactory的引用)中沉睡。

      BeanNameAware就是让Bean对Spring有知觉:

    public interface BeanNameAware extends Aware {
        void setBeanName(String var1);
    }

      BeanFactoryAware让Bean对工厂有知觉:

    public interface BeanFactoryAware extends Aware {
        void setBeanFactory(BeanFactory var1) throws BeansException;
    }

      代码如下:

    public class BeanTest implements BeanNameAware,BeanFactoryAware {
    
        private String beanName;
        private BeanFactory beanFactory;
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            this.beanFactory=beanFactory;       // 让Bean获取配置他们的BeanFactory的引用。
        }
    
        @Override
        public void setBeanName(String beanName) {
            this.beanName=beanName;     // 让Bean获取自己在BeanFactory配置中的名字(根据情况是id或者name)
        }
    }

      以上两个set方法Spring会自动调用:

      BeanName:会在Spring自身完成Bean配置之后,且在调用任何Bean生命周期回调(初始化或者销毁)方法之前就调用这个方法。换言之,在程序中使用BeanFactory.getBean(String beanName)之前,Bean的名字就已经设定好了。所以,程序中可以尽情的使用BeanName而不用担心它没有被初始化。

      BeanFactory:可能是在根据某个配置文件创建了一个新工厂之后,Spring才调用这个方法,并把BeanFactory注入到Bean中。 

    六、BeanPostProcessor接口

      BeanPostProcessor接口提供了两个默认实现:

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

      我们先来看一个例子,代码如下:

    public class User implements InitializingBean,DisposableBean {
        public User(){
            System.out.println("实例化User的构造方法......");
        }
        public void destroy() {
            System.out.println("调用实现DisposableBean的destroy方法....");
        }
        public void afterPropertiesSet() {
            System.out.println("调用实现InitializingBean的afterPropertiesSet方法......");
        }
        public void initUser(){
            System.out.println("执行initMethod方法.....");
        }
        public void destroyUser(){
            System.out.println("执行destroyMethod方法......");
        }
    }
    
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
        public Object postProcessBeforeInitialization(Object bean, String beanName)
                throws BeansException {
            // 这边只做简单打印   原样返回bean
            System.out.println("postProcessBeforeInitialization====" + beanName);
            return bean;
        }
    
        public Object postProcessAfterInitialization(Object bean, String beanName)
                throws BeansException {
            // 这边只做简单打印   原样返回bean
            System.out.println("postProcessAfterInitialization====" + beanName);
            return bean;
        }
    }
    
    @Configuration
    public class MainConfig {
    
        @Bean(initMethod = "initUser", destroyMethod = "destroyUser")
        public User getUser() {
            return new User();
        }
    
        @Bean
        public MyBeanPostProcessor getMyBeanPostProcessor() {
            return new MyBeanPostProcessor();
        }
    
        public static void main(String[] args) {
            // 使用AnnotationConfigApplicationContext获取spring容器ApplicationContext
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            applicationContext.close();
        }
    }

      测试结果如下:

    实例化User的构造方法......
    postProcessBeforeInitialization====getUser
    调用实现InitializingBean的afterPropertiesSet方法......
    执行initMethod方法.....
    postProcessAfterInitialization====getUser
    调用实现DisposableBean的destroy方法....
    执行destroyMethod方法......

      因此可以总结:

    1,首先执行bean的构造方法,
    2,BeanPostProcessor的postProcessBeforeInitialization方法
    3,InitializingBean的afterPropertiesSet方法
    4,@Bean注解的initMethod方法
    5,BeanPostProcessor的postProcessAfterInitialization方法
    6,DisposableBean的destroy方法
    7,@Bean注解的destroyMethod方法

      我们根据源码进行实例化Bean的确认(销毁同理):

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        // 省略部分代码。。。。
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 位置2的 BeanPostProcessor的postProcessBeforeInitialization方法执行的地方
            // 这也是为什么他执行所有的初始化之前的原因了
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
        try {
            // 初始化bean
            invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // 位置5的 BeanPostProcessor的PostProcessorsAfterInitialization方法执行的地方
            // 初始化完成之后执行BeanPostProcessor的postProcessorsAfterInitialization
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {
        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                // 位置3的 InitializingBean的afterPropertiesSet方法
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }
        if (mbd != null) {
            // 位置4的 @Bean注解的initMethod方法
            String initMethodName = mbd.getInitMethodName();
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

      注意:初始化开始于启动类AnnotationConfigApplicationContext.refresh()方法;销毁开始于applicationContext.close()方法。

  • 相关阅读:
    JAVA GUI设
    3.4 jmu-java-随机数-使用蒙特卡罗法计算圆周率的值 (10 分)
    问题:关于2.3 jmu-Java-02基本语法-03-身份证排序 (9 分)
    关于3.1 jmu-Java-03面向对象基础-01-构造函数与toString (3 分)
    linux vim文件编辑的常用命令
    linux的常用命令
    linux文件存储方式
    第一个java
    hdu 2795
    hdu 1394
  • 原文地址:https://www.cnblogs.com/jing99/p/12669861.html
Copyright © 2020-2023  润新知