这个接口有什么用?
ApplicationContextAware这个接口本身并不具备什么功能,一般用于子类继承后,子类重写接口的setApplicationContext(ApplicationContext context)方法,当在Spring初始化子类实例的时候,会调用该方法,这个方法将Spring上下文作为参数传入,可以方便地获取相应的资源,包括获取整个Spring容器(ApplicationContext)。
注意:一定要让继承ApplicationContextAware接口的bean被Spring上下文管理,在application.xml文件中定义对应的bean标签,或者使用@Component等注解。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Component public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.applicationContext = applicationContext; }
public static Object getBean(String name) { return applicationContext.getBean(name); }
public static <T> T getBean(Class<T> requiredType) { return applicationContext.getBean(requiredType); }
}
|
测试获取容器中的bean:
1 2 3 4 5
| @Test public void testGetBean() { DefaultNotifyStrategy bean = SpringContextUtil.getBean(DefaultNotifyStrategy.class); System.out.println(bean); }
|
输出:
1
| com.lzumetal.springboot.spring.service.DefaultNotifyStrategy@eb7b5e
|
使用示例扩展:获取指定注解的资源
1.在这个例子中,我们自定义了一个注解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.lzumetal.ssm.springinterface.annotation;
import org.springframework.stereotype.Service;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Service public @interface MyRpcService {
Class<?> value();
}
|
应为这个注解是包含了Spring的@Service注解,所以标注了这个注解的类也将被spring的IOC容器管理。
2.定义一个借口和实现类
1 2 3 4 5
| package com.lzumetal.ssm.springinterface.service;
public interface RpcDemoService {
}
|
1 2 3 4 5 6 7 8
| package com.lzumetal.ssm.springinterface.service;
import com.lzumetal.ssm.springinterface.annotation.MyRpcService;
@MyRpcService(RpcDemoService.class) public class RpcDemoServiceImpl implements RpcDemoService {
}
|
3.spring的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.lzumetal.ssm.springinterface"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
</beans>
|
4.定义ApplicationContextAware的子类,在这个子类中,我们就可以获取到标注了@Service的所有bean。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package com.lzumetal.ssm.springinterface;
import com.lzumetal.ssm.springinterface.annotation.MyRpcService; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils;
import java.util.HashMap; import java.util.Map;
@Component public class RpcServer implements ApplicationContextAware {
private Map<String, Object> handlerMap = new HashMap<>();
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(MyRpcService.class);
if (!CollectionUtils.isEmpty(serviceBeanMap)) { for (Object serviceBean : serviceBeanMap.values()) { MyRpcService myRpcService = serviceBean.getClass().getAnnotation(MyRpcService.class); String serviceName = myRpcService.value().getName(); handlerMap.put(serviceName, serviceBean); } } }
public Map<String, Object> getHandlerMap() { return handlerMap; }
public void setHandlerMap(Map<String, Object> handlerMap) { this.handlerMap = handlerMap; } }
|
5.简单测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.lzumetal.ssm.springinterface.test;
import com.lzumetal.ssm.springinterface.RpcServer; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring-context.xml"}) public class MainTest {
@Autowired private RpcServer rpcServer;
@Test public void testApplicationContextAware() { Map<String, Object> handlerMap = rpcServer.getHandlerMap(); for (Map.Entry<String, Object> entry : handlerMap.entrySet()) { System.out.println(entry.getKey() + "====>" + entry.getValue()); } } }
|
输出:
1
| com.lzumetal.ssm.springinterface.service.RpcDemoService====>com.lzumetal.ssm.springinterface.service.RpcDemoServiceImpl@5cee5251
|
后话
Spring中还有一个接口InitializingBean,它的子类会重写afterPropertiesSet()方法,当Spring初始化子类bean的时候,当属性被初始化后便会调用这个方法,和ApplicationContextAware相比是这个重写的方法是无参的。