Spring中ApplicationContextAware接口的用法
1. 这个接口有什么用?
加载Spring配置文件时,如果Spring配置文件中所定义或者注解自动注入的Bean类实现了ApplicationContextAware 接口,那么在加载Spring配置文件时,会自动调用ApplicationContextAware 接口中的方法:
public void setApplicationContext(ApplicationContext context) throws BeansException
2. 可以用它来干什么?
获得了ApplicationContext对象之后,就可以获取容器中的bean,问题是我在需要bean的地方自动注入不是一样可以获得这个bean吗?这么做ms多此一举哦?其实还有一个场景,当你需要使用静态方法的时候,但是这些静态方法又依赖了一些注入的bean,看到这里就了解了吧,好了,上一个实例,看如何把bean放到静态方法中使用
@Component
public class AppContextUtil implements ApplicationContextAware {
private static ApplicationContext appContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.appContext = applicationContext;
}
private static Object getBean(String beanName, Class clazz){
return appContext.getBean(beanName);
}
/**如果bean类中有方法做为切面的切入点(pointcut),那么getbean类型必须是接口,以接口的方式生成代理类,
* 否则会报错代理类无法转换成目标类型
* @return
*/
private static Action getDog(){
Action dog = (Action)appContext.getBean("dog", Action.class);
return dog;
}
/**如果bean的类是基于接口实现的,只要其中的方法没有做为切面的切入点,那么getbean的类型可以是实现类,也可以是接口
* @return
*/
private static Panda getPanda(){
return (Panda)appContext.getBean("panda", Panda.class);
}
public static void pandaDance(){
getPanda().dance();
}
public static void DogSay(){
Action dog = getDog();
dog.say();
}
}
@Component("dog")
public class Dog implements Action {
@Override
public void say() {
System.out.println("dog bark!");
}
@Override
public void run() {
try {
System.out.println("dog run!");
Thread.currentThread().sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Component("panda")
public class Panda implements Animal{
@Override
public void dance(){
System.out.println("panda dancing!");
}
}
如果Spring配置文件中所定义的Bean类实现了ApplicationContextAware 接口,那么在加载Spring配置文件时,会自动调用ApplicationContextAware 接口中的
public void setApplicationContext(ApplicationContext context) throws BeansException
在AppContextUtil类中定义一个类型为ApplicationContext的静态变量appContext,当Spring自动注入AppContextUtil的bean时,就会自动调用其setApplicationContext方法,把应用的context当做参数传进去,然后我们把它赋值给静态的appContext,这样在其他的静态方法中就可以通过appContext的getBean方法获取对应的bean,然后进行操作。
如上例所示:
private static Action getDog()
为什么返回类型是一个接口,而不是Dog类本身,因为在示例中,我做了一个切面类,把Dog类里的say()方法当做切入点,此时getBean必须指定接口类型,jdk默认以接口的方式实现代理类,否则会报错代理类不能转换成目标类型。
private static Panda getPanda()
这个静态方法返回的是Panda类(虽然它也实现了一个接口Animal),Panda类中没有方法被做为切入点,所以可以直接用目标类型,当然这里也可以用接口类型Animal