zoukankan      html  css  js  c++  java
  • ApplicationContextAware和BeanFactoryAware使用理解

    1.Spring容器会自动把上下文环境对象调用ApplicationContextAware接口中的setApplicationContext方法;当一个类实现了这个接口之后,这个类就可以非常方便的获取到ApplicationContext中的所有的bean;简而言之,言而总之,此类可以获取到spring配置文件中所有的bean对象。

    2.基本原理见如下代码,核心类:ApplicationContextAwareProcessor

    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
     
        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||    bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||    bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
                acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }
     
        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }
     
        return bean;
    }
     
    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
                }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                    new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

    在启动Spring容器创建bean的时候会执行postProcessBeforeInitialization这个方法,发现实现了Aware接口的类(例如最后一个ApplicationContextAware),都会加载spring的applicationContext。

    3.代码实例讲解(此处讲解通过实现BeanFactoryAware接口将bean注册到beanfactory中):
    首先通过实现BeanFactoryAware接口将bean注册到spring容器中。

    @Component
    public class BeanFactoryHelper implements BeanFactoryAware {
     
        private static BeanFactory beanFactory;
     
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            this.beanFactory = beanFactory;
        }
     
        public static BeanFactory getBeanFactory() {
            return this.beanFactory;
        }
    }
     
    //获取beanFactory并注册到spring上下文中
    DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) BeanFactoryHolder.getBeanFactory();
     
    String beanName = "test";
    beanFactory.destroySingleton(beanName);
     
    beanFactory.registerSingleton(beanName, singletonObject);

    注册到spring上下文之后就可以通过实现ApplicationContextAware接口来获取bean对象:

    @Component
    public class ApplicationContextHelper implements ApplicationContextAware {
        private static ApplicationContext ctx;
     
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.ctx = applicationContext;
        }
     
        public static ApplicationContext getApplicationContext() {
            return this.ctx;
        }
     
        public static Object getBean(String beanName) {
            return this.ctx.getBean(beanName);
        }
     
        public static <T> T getBean(Class<T> clazz) {
            return this.ctx.getBean(clazz);
        }
     
        public static <T> T getBean(String beanName, Class<T> clazz) {
            try {
                return this.ctx.getBean(beanName, clazz);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    上面两种方法,只有容器启动的时候,才会把BeanFactory和ApplicationContext注入到自定义的helper类中,如果在本地junit测试的时候,如果需要根据bean的名称获取bean对象,则可以通过ClassPathXmlApplicationContext来获取一个ApplicationContext,代码如下:

    @Test
        public void test() throws SQLException {
            //通过从classpath中加载spring-mybatis.xml实现bean的获取
            ApplicationContext context = new ClassPathXmlApplicationContext("spring-mybatis.xml");
            IUserService userService = (IUserService) context.getBean("userService");
    
            User user = new User();
            user.setName("test");
            user.setAge(20);
            userService.addUser(user);
        }

    本文转自:https://blog.csdn.net/jianjun200607/article/details/94986347

    https://www.cnblogs.com/handsomeye/p/6277510.html

  • 相关阅读:
    [Java] SSH框架笔记_框架分析+环境搭建+实例源码下载
    [JavaEE] WEB-INF有关的目录路径总结
    网站标题分隔符
    [Windows] 解决kmplayer播放rmvb文件音视不同步
    [MySQL] 数据统计 —— 按周,按月,按日分组统计数据
    [Java] JSTL格式化时间计算时差
    [C.Sharp] TimeSpan的用法,获取测试程序运行时间
    [设计模式] .NET设计模式笔记
    Spring Boot使用redis做数据缓存
    Spring Boot使用redis做数据缓存
  • 原文地址:https://www.cnblogs.com/nizuimeiabc1/p/12178279.html
Copyright © 2011-2022 走看看