上下文,这是一个比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();
运行结果: