ApplicationContextAware和BeanFactoryAware使用理解


1.Spring容器會自動把上下文環境對象調用ApplicationContextAware接口中的setApplicationContext方法;當一個類實現了這個接口之后,這個類就可以非常方便的獲取到ApplicationContext中的所有的bean;簡而言之,言而總之,此類可以獲取到spring配置文件中所有的bean對象。BeanFactoryAware實現這個接口的bean是希望知道自己屬於哪一個beanFactory(就是加載bean的applicationContext上下文,有xml方式,注解方式等)。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM