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
来源:https://www.cnblogs.com/nizuimeiabc1/p/12178279.html