SpringBoot普通类获取spring容器中bean的操作
前言
在spring框架中,是无法在普通类中通过注解注入实例的,因为sping框架在启动的时候,就会将标明交给spring容器管理的类进行实例化,并梳理他们彼此的依赖关系,进行注入,没有交给spring容器管理的普通类,是不会进行注入的,即使你使用了注入的相关注解。这个时候,如果我们需要在普通类中获取spring容器中的实例,就需要一些特定的方法,这里将整理一下如何在springboot中实现这样的方法。
创建springboot工程demo
项目结构图示
项目结构说明
service包下为demo接口和实现类,添加@Service注解,标明交由spring框架管理实例。
test包下为测试用的普通类,测试获取实例的方法。
utils包下为自定义的获取spring容器中实例的方法。
工程代码
service
package com.demo.service; public interface IDemoService { String demo(); }
package com.demo.service.impl; import com.demo.service.IDemoService; import org.springframework.stereotype.Service; @Service public class DemoServiceImpl implements IDemoService { @Override public String demo() { return "Hello World"; } }
@Service注解标明了此实例交由spring容器管理
test
package com.demo.test; import com.demo.service.IDemoService; import com.demo.utils.BeanUtil; public class Test { public void test(){ //获取已经实例化的接口bean IDemoService bean = BeanUtil.getBean(IDemoService.class); //执行bean中方法 String demo = bean.demo(); //输出结果 System.out.println(demo); } }
utils
package com.demo.utils; import org.springframework.context.ConfigurableApplicationContext; public class BeanUtil { //将管理上下文的applicationContext设置成静态变量,供全局调用 public static ConfigurableApplicationContext applicationContext; //定义一个获取已经实例化bean的方法 public static <T> T getBean(Class<T> c){ return applicationContext.getBean(c); } }
启动类
package com.demo; import com.demo.test.Test; import com.demo.utils.BeanUtil; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication() public class DemoApplication { public static void main(String[] args) { //run方法的返回值ConfigurableApplicationContext继承了ApplicationContext上下文接口 ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args); //将run方法的返回值赋值给工具类中的静态变量 BeanUtil.applicationContext = applicationContext; //测试获取已经实例化的接口bean,执行bean中方法 new Test().test(); } }
测试效果
可以看到,test方法应成功获取DemoService接口实例,这里总结的是springboot工程在普通类获取sping容器中实例的方法,其原理和传统方法其实都是一样的,获取上下文环境,从上下文环境中拿到spring容器管理的实例。
补充知识:SpringBoot获取Bean
一种最简单的方法是实现ApplicationContextAware类来获取容器中的bean:
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.applicationContext = applicationContext; } //获取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); } }
我们可以通过bean的名称、bean的类型或者bean的名称+类型来获取容器中的bean。
默认情况下,Spring容器中的bean是单例的,为此我做了一个测试,我创建了两个bean,一个是默认的,一个是我指定多例的:
import org.springframework.stereotype.Service; /** * 这是一个单例的bean */ @Service public class BeanSingletonService { }
import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; /** * 这是一个多例的bean */ @Service @Scope("prototype") public class BeanPrototypeService { }
验证下我的想法:
import com.xqnode.learning.common.config.SpringContextUtil; import com.xqnode.learning.service.BeanPrototypeService; import com.xqnode.learning.service.BeanSingletonService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class LearningApplicationTests { @Test public void contextLoads() { BeanSingletonService s1 = SpringContextUtil.getBean(BeanSingletonService.class); BeanSingletonService s2 = SpringContextUtil.getBean(BeanSingletonService.class); BeanPrototypeService p1 = SpringContextUtil.getBean(BeanPrototypeService.class); BeanPrototypeService p2 = SpringContextUtil.getBean(BeanPrototypeService.class); System.out.println("s1==s2: " + s1.equals(s2)); System.out.println("p1==p2: " + p1.equals(p2)); } }
从结果中可以看到默认的BeanSingletonService 这个bean是单例的,两个对象完全相等,而我指定的BeanPrototypeService 这个bean则是多例的,两个bean不相同。
以上这篇SpringBoot普通类获取spring容器中bean的操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。