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