上下文,這是一個比BeanFactory
功能更增強大的容器,可是具體ApplicationContext
都有些什麼強大的功能呢?一塊兒來看看吧。java
其實看ApplicationContext
所繼承的接口,就能明白都有些什麼功能,這裏說一說我以爲比較重要的一個功能——ApplicationEventPublisher
:程序事件發佈。spring
通俗來講就是我這個容器運行時會發布一些事件,而後咱們能夠對這些容器發佈的事件進行監聽。ide
@Component public class TestListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { System.out.println("我是一個監聽程序啓動的方法"); } } @ComponentScan("com.mengyunzhi.spring") public class Application { public static void main(String []args) { ApplicationContext context = new AnnotationConfigApplicationContext(Application.class); } }
ApplicationListener
,函數式接口,用於監聽某個繼承自ApplicationEvent
類型的事件,當該事件發佈時,執行咱們實現的onApplicationEvent
方法。函數
除了咱們使用的事件ContextRefreshedEvent
容器初始化或刷新以外,還有ContextClosedEvent
容器即將關閉,RequestHandledEvent
請求處理後發佈的事件。spa
運行結果:code
能夠實現Spring
提供的Ordered
接口,實現其生命的getOrder
方法,返回的值越小表示執行越靠前。xml
@Component public class TestListener implements ApplicationListener<ContextRefreshedEvent>, Ordered { @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { System.out.println("我是一個監聽程序啓動的方法"); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } } @Component public class NewListener implements ApplicationListener<ContextRefreshedEvent>, Ordered { @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { System.out.println("我是一個新的監聽方法"); } @Override public int getOrder() { return Ordered.LOWEST_PRECEDENCE; } }
運行結果:對象
熟悉不過的自動裝配,@Autowired
註解的本質是根據Bean
的類型進行裝配,就是舊版本Spring
中的ByType
方式。blog
@Autowired private TestService testService;
聲明須要一個TestService
類型的對象,而後Spring
會在上下文中尋找符合條件的Bean
,並未咱們注入進來。繼承
而若是一個接口有多個實現,在上下文中就會有多個符合該條件的Bean
,因此咱們就須要對注入的Bean
進行ByName
聲明,根據Bean
的名稱進行注入。使用註解@Qualifier
進行根據名稱的裝配。
如今實現類上爲該組件聲明一個名稱,或者在xml
配置中爲該Bean
配置名稱。
@Service("TestServiceImpl") public class TestServiceImpl implements TestService { @Override public void show() { System.out.println("我是TestServiceImpl, TestService的實現"); } } @Service("NewTestServiceImpl") public class NewTestServiceImpl implements TestService { @Override public void show() { System.out.println("我是NewTestServiceImpl, 也是TestService的實現"); } }
運行結果:
若是咱們一個接口有多個實現類,可是98%
的業務環境下都須要注入咱們的NewTestServiceImpl
實例,咱們不肯意寫那麼多的Qualifier
,因此咱們能夠聲明某個類爲Primary
而被優先注入。極少數狀況下須要別的實例的話再去Qualifier
聲明。
@Primary @Service("NewTestServiceImpl") public class NewTestServiceImpl implements TestService { @Override public void show() { System.out.println("我是NewTestServiceImpl, 也是TestService的實現"); } }
運行結果:
某些業務環境,可能一個Bean
在執行完構造函數以後還不能被使用,還須要執行一些初始化操做,畢竟優雅的代碼應該把對象的構造與初始化分開。
@Service public class NewTestServiceImpl implements TestService { @PostConstruct public void init() { System.out.println("我是init方法,我初始化NewTestServiceImpl"); } @PreDestroy public void destroy() { System.out.println("我是destroy方法,我銷燬NewTestServiceImpl"); } }
使用@PostConstruct
標註在對象創造以後執行的初始化操做,使用@PreDestroy
標註在對象銷燬以前執行的銷燬邏輯。
ApplicationContext context = new AnnotationConfigApplicationContext(Application.class); ((AnnotationConfigApplicationContext) context).close();
運行結果: