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