https://blog.csdn.net/zsw12013/article/details/51701671
____________________________________________________________________________________________________________________________
SpringBoot中获取ApplicationContext的三种方式
ApplicationContext是什么?
简单来说就是Spring中的容器,可以用来获取容器中的各种bean组件,注册监听事件,加载资源文件等功能。
Application Context获取的几种方式
1 直接使用Autowired注入
@Component
public class Book1 {
@Autowired
private ApplicationContext applicationContext;
public void show (){
System.out.println(applicationContext.getClass());
}
}
2 利用 spring4.3 的新特性
使用spring4.3新特性但是存在一定的局限性,必须满足以下两点:
1 构造函数只能有一个,如果有多个,就必须有一个无参数的构造函数,此时,spring会调用无参的构造函数
2 构造函数的参数,必须在spring容器中存在
@Component
public class Book2 {
private ApplicationContext applicationContext;
public Book2(ApplicationContext applicationContext){
System.out.println(applicationContext.getClass());
this.applicationContext=applicationContext;
}
public void show (){
System.out.println(applicationContext.getClass());
}
}
3 实现spring提供的接口 ApplicationContextAware
spring 在bean 初始化后会判断是不是ApplicationContextAware的子类,调用setApplicationContext()方法, 会将容器中ApplicationContext传入进去
@Component
public class Book3 implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void show (){
System.out.println(applicationContext.getClass());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
结果获取三次:
class org.springframework.context.annotation.AnnotationConfigApplicationContext
class org.springframework.context.annotation.AnnotationConfigApplicationContext
class org.springframework.context.annotation.AnnotationConfigApplicationContext
---------------------
版权声明:本文为CSDN博主「A 是小阿怪啊」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38361347/article/details/89304414
___________________________________________________________________________________________________
在项目中我们经常会碰到这么一个场景,某些普通的JAVA类,这个类并没有被Spring所管理,但是我们需要再这个类中调用到某些方法,是ioc容器中对象的方法,我们没法再普通的JAVA类中通过spring的注解@Autowired和@Resource注入对象,在这种场景下,我么就可以使用方法获取到ioc中的实例,并使用其方法。
在项目中获取获取beand方法多种多样,这里大致列举几种
- 在初始化时保存ApplicationContext对象
- 通过Spring提供的utils类获取ApplicationContext对象
- 继承自抽象类ApplicationObjectSuppor
- 继承自抽象类WebApplicationObjectSupport
- 实现接口ApplicationContextAware
- 通过Spring提供的ContextLoader
如果想了解每一种的用法可以参考此篇博文:https://blog.csdn.net/zsw12013/article/details/51701671
本片博文只具体展示一种配置,也是自身项目中遇到的获取方式,就是第五中方式实现接口ApplicationContextAware,这种获取方式适用于大多数项目内业务接口不方便注入的时候的调用
实现ApplicationContextAware接口的类必须要被spring所管理,要么在代码中标记为ioc组件(类的路径必须要被spring扫描到),要么在applicationContext.xml spring的配置文件配置为bean,不然会获取不到上下文对象,调用这个类的普通JAVA类是没有限制的。
工具类代码
package com.wzh.config.utils;
import org.apache.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * <从Spring IOC容器中获取Bean对象> <功能详细描述> * @author wzh * @version 2018-09-23 19:32 * @see [相关类/方法] (可选) **/ @Component("beanHeader") public class BeanHeader implements ApplicationContextAware { private static Logger log = Logger.getLogger(BeanHeader.class); // 上下文对象 private static ApplicationContext applicationContext; /** * 实现ApplicationContextAware接口的回调方法,注入上下文对象 * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { BeanHeader.applicationContext = applicationContext; } /** * 获取上下文对象 * @return applicationContext */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 判断上下文对象是否为空 * * @return */ public static boolean checkapplicationContext() { boolean flag = getApplicationContext() != null; if (!flag) { log.error("applicaitonContext未注入,实现ApplicationContextAware的类必须被spring管理"); } return flag; } /** * 根据name获取bean * @param name * @param <T> * @return */ public static <T> T getBean(String name) { if (checkapplicationContext()) { return (T)getApplicationContext().getBean(name); } else { return null; } } /** * 根据class 获取bean * @param clazz * @param <T> * @return */ public static <T> T getBean(Class<T> clazz) { if (checkapplicationContext()) { return getApplicationContext().getBean(clazz); } else { return null; } } /** * 根据name,以及Clazz返回指定的Bean * @param name * @param clazz * @param <T> * @return */ public static <T> T getBean(String name, Class<T> clazz) { if (checkapplicationContext()) { return getApplicationContext().getBean(name, clazz); } else { return null; } } }
下面我们来测试一下
首先是一个简单的service 被spring管理
package com.wzh.demo.service.impl;
import com.wzh.demo.service.SystemOutService;
import org.springframework.stereotype.Service;
/**
* <简单的输出测试,没有功能>
* <功能详细描述>
* @author wzh * @version 2018-09-23 23:11 * @see [相关类/方法] (可选) **/ @Service("systemOutService") public class SystemOutServiceImp implements SystemOutService{ @Override public void sysout() { System.out.println("调用systemOutService 成功"); } }
junit 测试基类
package base;
import com.wzh.application.Application;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; /** * junit 测试基类 */ //SpringJUnit支持,由此引入Spring-Test框架支持! @RunWith(SpringJUnit4ClassRunner.class) //启动类,启用随即端口 @SpringBootTest(classes = Application.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) //web项目支持,webEnvironment属性使用后不能用webAppconfiguration注解 //@WebAppConfiguration public class BaseJunit { @Test public void runJunitTest() { System.out.println("Junit 启动测试"); } }
junit 测试类
import base.BaseJunit;
import com.wzh.config.utils.BeanHeader;
import com.wzh.demo.service.SystemOutService;
import org.junit.Test;
/** * <一句话功能描述> * <功能详细描述> * @author wzh * @version 2018-09-23 23:18 * @see [相关类/方法] (可选) **/ public class BeanHeaderTest extends BaseJunit { @Test public void testBeanHeader() { SystemOutService service = BeanHeader.getBean("systemOutService"); service.sysout(); } }
运行方法,控制台输出
_____________________________________________________________________________________________
在正常情况下 spring管理的类可直接调用Ioc容器中的实例,但在一些特殊情况下(例如拦截器中获取dao实例),Bean需要实现某个功能,但该功能必须借助于Spring容器才能实现,此时就必须让该Bean先获取Spring容器,
spring提供了ApplicationContextAware接口,容器会自动检索实现该接口的类进行spring上下文注入
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
log.info("ApplicationContext config success");
}
// 获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
// 通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
// 通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
// 通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
使用例子,拦截器中获取 redis缓存实例
public class AccessInterceptor implements HandlerInterceptor {
private IStringCacheService cache = SpringUtil.getBean(IStringCacheService.class);
......
......
......
......
......
}