Spring获取容器中的Bean的接口ApplicationContextAware

在Web应用中,Spring容器通常采用声明式方式配置产生:开发者只要在web.xml中配置一个Listener,该Listener将会负责初始化Spring容器,MVC框架可以直接调用Spring容器中的Bean,无需访问Spring容器本身。在这种情况下,容器中的Bean处于容器管理下,无需主动访问容器,只需接受容器的依赖注入即可。

在某些的情况下,我们要获取IOC容器中指定注解、类型、名字的Bean,来实现某个功能
实现上,我们不用类似new ClassPathXmlApplicationContext()的方式,从已有的spring上下文取得已实例化的bean。通过ApplicationContextAware接口进行实现。
当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean。换句话说,就是这个类可以直接获取spring配置文件中,所有有引用到的bean对象

以下实例采用SpringBoot + idea:

AppBeanUtil。java:
@Component("appBeanUtil")
public class AppBeanUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;
    /**
     * 实现ApplicationContextAware接口, 注入Context到本类的静态变量中.
    */
    public void setApplicationContext(ApplicationContext preapplicationContext)  {
        AppBeanUtil.applicationContext = preapplicationContext;
    }
    /**
     * 获取静态变量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * 从静态变量applicationContext中得到指定名字的 Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(String beanName) {
        return (T)applicationContext.getBean(beanName);
    }
    /**
     * 从静态变量applicationContext中得到指定名字、类型的 Bean, 自动转型为所赋值对象的类型.其中指定的类型可以是其父类或所实现的接口
     */
    public static <T> T getBean(String beanName, Class<T> clz) {
        return applicationContext.getBean(beanName, clz);
    }

    /**
     * 根据传入的自定义注解的类,从Application获取有此注解的所有类
     * @param cls
     * @return
     */
    public static Map<String, Object> getMapbeanwithAnnotion(Class<? extends Annotation> cls) {
        Map<String, Object> map = new HashMap<String, Object>();
        map = applicationContext.getBeansWithAnnotation(cls);
        return map;
    }

    /**
     * 根据类型获取spring容器中的实例
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> Map<String,T> getBeansOfType(Class<T> clazz){
        assertContextInjected();
        return applicationContext.getBeansOfType(clazz);
    }
    /**
     * 检查ApplicationContext不为空.
     */
    private static void assertContextInjected() {
        Validate.validState(applicationContext != null,"applicaitonContext属性未注入!");
    }
    /**
     * 清除SpringContextHolder中的ApplicationContext为Null.
     */
    public static void clearHolder() {
        applicationContext = null;
    }

}

Spring容器会检测容器中的所有Bean,如果发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContextAware()方法,调用该方法时,会将容器本身作为参数传给该方法——该方法中的实现部分将Spring传入的参数(容器本身)赋给该类对象的applicationContext实例变量,因此接下来可以通过该applicationContext实例变量来访问容器本身

Person.java

public abstract class Person {
    public abstract String getName(String name);
}

Stu.java

@Component
public class Stu extends Person {
    @Override
    public String getName(String name) {
        System.out.println("Stu call...");
        String result = "I am a Stu,username:" + name;
        return result;
    }
}

Tea.java

@Component
public class Tea extends Person {
    @Override
    public String getName(String name) {
        System.out.println("Tea call...");
        String result = "I am a Tea,username:" + name;
        return result;
    }
}

测试Demo

@Component
//@DependsOn(value = "appBeanUtil")
public class TestTask {
    //@Scheduled(cron = "${cron.timer}")
    @Scheduled(cron = "0/2 0/1 * * * ? ")
    public void test(){
        System.out.println("定时器运行了!!! start....");
        Map<String, Person> beans = AppBeanUtil.getBeansOfType(Person.class);

        if (MapUtils.isNotEmpty(beans)) {
            for (Person bean : beans.values()) {
                String userName = bean.getName("zhangsan");
                System.out.println(userName);
            }
        }

        System.out.println("定时器运行了!!! end....");
    }
}

结果:

猜你喜欢

转载自blog.csdn.net/jc_benben/article/details/106943220
今日推荐