2 bean配置檔案指定init-method、destroy-method
Spring允許我們建立自己的 init 方法和 destroy 方法。隻要在 Bean 的配置檔案中指定
init-method
和
destroy-method
的值就可以在 Bean 初始化時和銷毀之前執行一些操作。
案例
public class GiraffeService {
// 通過<bean>的destroy-method屬性指定的銷毀方法
public void destroyMethod() throws Exception {
System.out.println("執行配置的destroy-method");
}
// 通過<bean>的init-method屬性指定的初始化方法
public void initMethod() throws Exception {
System.out.println("執行配置的init-method");
}
}
配置檔案中的配置:
<bean name="giraffeService" class="com.giraffe.spring.service.GiraffeService" init-method="initMethod" destroy-method="destroyMethod">
</bean>
自定義的init-method和post-method方法可以抛異常,但不能有參數。
這種方式比較推薦,因為可以自己建立方法,無需将Bean的實作直接依賴于Spring架構。
@PostConstruct、@PreDestroy
這兩個注解均在
javax.annotation
包。
Spring 支援用
@PostConstruct
@PreDestroy
注解指定
init
destroy
方法。
為使注解生效,需在配置檔案中定義
- org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
- 或context:annotation-config
public class GiraffeService {
@PostConstruct
public void initPostConstruct(){
System.out.println("執行PostConstruct注解标注的方法");
}
@PreDestroy
public void preDestroy(){
System.out.println("執行preDestroy注解标注的方法");
}
}
配置檔案:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
實作Aware接口
在Bean中使用Spring架構的一些對象
有些時候我們需要在 Bean 的初始化中使用 Spring 架構自身的一些對象來執行一些操作,比如
- 擷取 ServletContext 的一些參數
- 擷取 ApplicaitionContext 中的 BeanDefinition 的名字
- 擷取 Bean 在容器中的名字等等。
為了讓 Bean 可以擷取到架構自身的一些對象,Spring 提供了一組名為Aware的接口。
這些接口均繼承于org.springframework.beans.factory.Aware标記接口,并提供一個将由 Bean 實作的set方法,Spring通過基于setter的依賴注入方式使相應的對象可以被Bean使用。
介紹一些重要的Aware接口:
ApplicationContextAware
獲得ApplicationContext對象,可以用來擷取所有Bean definition的名字。
任何希望被通知它運作的ApplicationContext對象要實作的接口。
例如,當一個對象需要通路一組協作 bean 時。通過 bean 引用進行配置比僅為了bean=查找而實作此接口更有意義!
如果對象需要通路檔案資源,即想要調用getResource ,想要釋出應用程式事件,或者需要通路 MessageSource,也可以實作此接口。 但是,在這種特定場景中,最好實作更具體的ResourceLoaderAware 、 ApplicationEventPublisherAware或MessageSourceAware接口。
請注意,檔案資源依賴項也可以作為org.springframework.core.io.Resource類型的 bean 屬性公開,通過字元串填充,并由 bean 工廠進行自動類型轉換。 這消除了為了通路特定檔案資源而實作任何回調接口的需要。
org.springframework.context.support.ApplicationObjectSupport是應用程式對象的一個友善的基類,實作了這個接口。
實作該接口的類,通過方法setApplicationContext()獲得該對象所運作在的ApplicationContext。一般用于初始化object。
在填充普通 bean 屬性之後但在初始化回調之前調用,例如:
- org.springframework.beans.factory.InitializingBean.afterPropertiesSet()
- 或自定義初始化方法
在:
- ResourceLoaderAware.setResourceLoader
- ApplicationEventPublisherAware.setApplicationEventPublisher
- 和MessageSourceAware之後調用(如果适用)。
- BeanFactoryAware:獲得BeanFactory對象,可以用來檢測Bean的作用域。
- BeanNameAware:獲得Bean在配置檔案中定義的名字。
- ResourceLoaderAware:獲得ResourceLoader對象,可以獲得classpath中某個檔案。
- ServletContextAware:在一個MVC應用中可以擷取ServletContext對象,可以讀取context中的參數。
- ServletConfigAware: 在一個MVC應用中可以擷取ServletConfig對象,可以讀取config中的參數。
public class GiraffeService implements ApplicationContextAware,
ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,
BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware{
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("執行setBeanClassLoader,ClassLoader Name = " + classLoader.getClass().getName());
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("執行setBeanFactory,setBeanFactory:: giraffe bean singleton=" + beanFactory.isSingleton("giraffeService"));
}
@Override
public void setBeanName(String s) {
System.out.println("執行setBeanName:: Bean Name defined in context="
+ s);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("執行setApplicationContext:: Bean Definition Names="
+ Arrays.toString(applicationContext.getBeanDefinitionNames()));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("執行setApplicationEventPublisher");
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("執行setEnvironment");
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
Resource resource = resourceLoader.getResource("classpath:spring-beans.xml");
System.out.println("執行setResourceLoader:: Resource File Name="
+ resource.getFilename());
}
@Override
public void setImportMetadata(AnnotationMetadata annotationMetadata) {
System.out.println("執行setImportMetadata");
}
}
BeanPostProcessor
允許自定義修改新 bean 執行個體的工廠鈎子——如檢查标記接口或用代理包裝 bean。
- 通過标記接口或類似方式填充bean的後置處理器将實作postProcessBeforeInitialization(java.lang.Object,java.lang.String)
- 而用代理包裝bean的後置處理器通常會實作postProcessAfterInitialization(java.lang.Object,java.lang.String)
Registration
一個ApplicationContext可在其 Bean 定義中自動檢測 BeanPostProcessor Bean,并将這些後置處理器應用于随後建立的任何 Bean。
普通的BeanFactory允許對後置處理器進行程式設計注冊,将它們應用于通過Bean工廠建立的所有Bean。
Ordering
在 ApplicationContext 中自動檢測的 OrderBeanPostProcessor Bean 将根據 PriorityOrdered 和 Ordered 語義進行排序。
相比之下,在BeanFactory以程式設計方式注冊的BeanPostProcessor bean将按注冊順序應用
對于以程式設計方式注冊的後處理器,通過實作 PriorityOrdered 或 Ordered 接口表達的任何排序語義都将被忽略。
對于 BeanPostProcessor bean,并不考慮 @Order 注解。