ApplicationContextAware和BeanFactoryAware使用理解

1.Spring容器会自动把上下文环境对象调用ApplicationContextAware接口中的setApplicationContext方法;当一个类实现了这个接口之后,这个类就可以非常方便的获取到ApplicationContext中的所有的bean;简而言之,言而总之,此类可以获取到spring配置文件中所有的bean对象,看到—Aware就知道是干什么的了,就是属性注入的,但是这个ApplicationContextAware的不同地方在于,实现了这个接口的bean,当spring容器初始化的时候,会自动的将ApplicationContext注入进来。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。

自己写的demo:

复制代码
/**  
* @Title: SpringJobBeanFactory.java
* @Package com.founder.mrp.job
* @Description: TODO
* @version V1.0  
*/

package com.founder.mrp.job;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringJobBeanFactory implements ApplicationContextAware {

    
    private static ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringJobBeanFactory.applicationContext=applicationContext;
        
    }
     public static ApplicationContext getApplicationContext() {
            return applicationContext;
    }
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
            if (applicationContext == null){
                return null;
            }
            return (T)applicationContext.getBean(name);
      }
}


使用:
TypeSetErpService typeSetErpServ = SpringJobBeanFactory.getBean("typeSetErpServiceImpl");
复制代码

String className=Thread.currentThread().getStackTrace[2].getClassName();

if(className.contains("ApplicationContextAwareProcessor"){this.applicationContext=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

https://www.cnblogs.com/loong-hon/p/10917755.html

posted @   ppjj  阅读(2404)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示