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()方法。