欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在spring上下文中获取bean

程序员文章站 2022-06-14 19:23:01
...

使用spring技术的web应用中,如何在程序中获取Spring上下文ApplicationContext,有两种方式:

1:实现ApplicationContextAware接口(实现此接口的setApplicationContext方法),在web应用中,spring会在启动时加载springContext上下文,spring的配置文件中配置了<context:component-scan/>会扫描配置了@Component注解的类,当扫描到实现了ApplicationContextAware接口的类时,spring启动线程会自动调用此类中的setApplicationContext方法,这样就可以将spring上下文注入到此类中的成员变量中(假设此变量的名称为applicationContext)。

使用main方法测试此类时,可以使用ClassPathXmlApplicationContext的构造器去加载spring上下文,然后让spring的启动线程去走完上述流程。web.xml的加载顺序是context-param->Listener(一般这里配置的spring的Listener接口即ContextLoaderListener)->filter->servlet(springmvc作为第一个Servlet加载),先加载tomcat中的ServletContext,再加载spring上下文,再加载springmvc上下文。spring的加载配置文件的机制:在web.xml中配置listen-class:org.springframework.web.context.ContextLoaderListener,此类是spring容器的入口,此接口有contextInitialized方法(初始化 root web application context)和contextDestroyed方法(销毁the root web application context).在项目启动时在ContextLoader的initWebApplicationContext的方法中打断点,此时的servletContext对象中的context是org.apache.catalina.core.ApplicationContext,继续走是使用WebappClassLoader去加载XmlWebApplicationContext上下文,继续走到BeanUtils.instantiateClass方法中使用clazz.getDeclaredConstructor()来获取一个默认构造器,后面过程略过。

@Component
public class SpringContextHolder implements ApplicationContextAware {
	
	private static ApplicationContext applicationContext;

	private volatile static int i = 0 ;

	// 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
	public synchronized void setApplicationContext(ApplicationContext applicationContext) {
		System.out.println("i : " + (++i));
		SpringContextHolder.applicationContext = applicationContext;
	}

	// 取得存储在静态变量中的ApplicationContext.
	public static ApplicationContext getApplicationContext() {
		checkApplicationContext();
		return applicationContext;
	}

	// 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String name) {
		checkApplicationContext();
		return (T) applicationContext.getBean(name);

	}

	public static Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
		checkApplicationContext();
		return applicationContext.getBeansWithAnnotation(annotationType);
	}

	// 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
	// 如果有多个Bean符合Class, 取出第一个.
	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<T> clazz) {
		checkApplicationContext();
		@SuppressWarnings("rawtypes")
		Map beanMaps = applicationContext.getBeansOfType(clazz);
		if (beanMaps != null && !beanMaps.isEmpty()) {
			return (T) beanMaps.values().iterator().next();
		} else {
			return null;
		}
	}

	public static <T> Map<String, T> getBeanMap(Class<T> clazz) {
		checkApplicationContext();
		return applicationContext.getBeansOfType(clazz);
	}

	private static void checkApplicationContext() {
		if (applicationContext == null) {
			throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
		}
	}
	
	public static void main(String[] args) {
		applicationContext = new ClassPathXmlApplicationContext("cfg-spring/spring-application.xml");
		Map<String, Object> map = SpringContextHolder.getBeansWithAnnotation(InitService.class);
		Iterator<Map.Entry<String, Object>> iter = map.entrySet().iterator();
		while(iter.hasNext()){
			Entry<String, Object> next = iter.next();
			System.out.println(next.getKey() + " : " + next.getValue());
		}
	}

 2:继承ApplicationObjectSupport(直接在当前类中使用this.getApplicationContext())

例如:Map<String, Object> map = this.getApplicationContext().getBeansWithAnnotation(InitService.class) 直接中map中获取对应注解(InitService)值的class

相关标签: spring springmvc