获取所有spring管理的bean
本文我们探索使用不同的方式获取spring容器中所有bean。
IOC容器
bean是基于spring应用的基础,所有bean都驻留在ioc容器中,由容器负责管理bean生命周期
有两种方式可以获取容器中的bean:
- 使用ListableBeanFactory接口
- 使用Spring Boot Actuator
使用ListableBeanFactory接口
ListableBeanFactory接口提供了getBeanDefinitionNames() 方法,能够返回所有定义bean的名称。该接口被所有factory实现,负责预加载bean定义去枚举所有bean实例。官方文档提供所有其子接口及其实现。
下面示例使用Spring Boot 构建:
首先,我们创建一些spring bean,先定义简单的Controller FooController:
1
2
3
4
5
6
7
8
9
10
11
|
@Controller
public class FooController {
@Autowired
private FooService fooService;
@RequestMapping (value= "/displayallbeans" )
public String getHeaderAndBody(Map model){
model.put( "header" , fooService.getHeader());
model.put( "message" , fooService.getBody());
return "displayallbeans" ;
}
}
|
该Controller依赖另一个spring Bean FooService:
1
2
3
4
5
6
7
8
9
10
11
|
@Service
public class FooService {
public String getHeader() {
return "Display All Beans" ;
}
public String getBody() {
return "This is a sample application that displays all beans "
+ "in Spring IoC container using ListableBeanFactory interface "
+ "and Spring Boot Actuators." ;
}
}
|
我们创建了两个不同的bean:
1.fooController
2.fooService
现在我们运行该应用。使用applicationContext 对象调用其 getBeanDefinitionNames() 方法,负责返回applicationContext上下文中所有bean。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@SpringBootApplication
public class Application {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(Application. class , args);
displayAllBeans();
}
public static void displayAllBeans() {
String[] allBeanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : allBeanNames) {
System.out.println(beanName);
}
}
}
|
会输出applicationContext上下文中所有bean:
fooController
fooService
//other beans
需注意除了我们定义的bean外,它还将打印容器中所有其他bean。为了清晰起见,这里省略了很多。
使用Spring Boot Actuator
Spring Boot Actuator提供了用于监视应用程序统计信息的端点(endpoint)。除了/beans,还包括很多其他端点,官方文档有详细说明。
现在我们访问url: http//
:/beans,如果没有指定其他独立管理端口,我们使用缺省端口,结果会返回json,包括容器所有定义的bean信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
[
{
"context" : "application:8080" ,
"parent" : null ,
"beans" : [
{
"bean" : "fooController" ,
"aliases" : [],
"scope" : "singleton" ,
"type" : "com.baeldung.displayallbeans.controller.FooController" ,
"resource" : "file [E:/Workspace/tutorials-master/spring-boot/target
/classes/com/baeldung/displayallbeans/controller/FooController. class ]",
"dependencies" : [
"fooService"
]
},
{
"bean" : "fooService" ,
"aliases" : [],
"scope" : "singleton" ,
"type" : "com.baeldung.displayallbeans.service.FooService" ,
"resource" : "file [E:/Workspace/tutorials-master/spring-boot/target/
classes/com/baeldung/displayallbeans/service/FooService. class ]",
"dependencies" : []
},
// ...other beans
]
}
]
|
当然,结果同样包括很多其他的bean,为了简单起见,这里没有列出。
小结一下
上面介绍了使用ListableBeanFactory 接口和 Spring Boot Actuators 返回spring 容器中所有定义的bean信息。
spring管理bean的原理
Spring容器默认情况下,当服务启动时,解析配置文件,实例化文件中的所有类。
使用spring时,获取spring注入的bean是这样
1
2
|
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
MyService myService1 = (MyService) ctx.getBean("myService");
|
那下面我们模拟spring管理bean这个的过程
代码如下:
1.第一步,创建java project,引入spring.jar
2.创建spring.xml配置文件
1
2
3
4
|
<? xml version = "1.0" encoding = "UTF-8" ?>
< beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" >
</ beans >
|
3.创建接口MyService,只需要一个测试方法save
4.创建实现类MyServiceImpl,控制台输出一句话
5.创建一个自己的解析类MyClassPathXmlApplicationContext
主要是构造方法中的两步
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
// 装载实例化bean
private Map<String, Object> beanMap = new HashMap<String, Object>();
// 装载配置文件的属性和值
private List<MyBeans> beanlist = new ArrayList<MyBeans>();
public MyClassPathXmlApplicationContext(String filename) {
//第一步,解析spring配置文件
readXml(filename);
//第二步,通过反射,实例化所有注入bean
initBeans();
}
/**
* 通过反射机制,初始化配置文件中的bean
*/
private void initBeans() {
for (MyBeans bean : beanlist) {
try {
if (bean.getClassName() != null && ! "" .equals(bean.getClassName())) {
beanMap.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 解析配置文件,把解析后的bean设置到实体中,并保持到list
*
* @param filename
*/
private void readXml(String filename) {
SAXReader reader = new SAXReader();
Document doc = null ;
URL xmlpath = this .getClass().getClassLoader().getResource(filename);
try {
Map<String, String> nsMap = new HashMap<String, String>();
nsMap.put( "ns" , "http://www.springframework.org/schema/beans" );
doc = reader.read(xmlpath);
XPath xpath = doc.createXPath( "//ns:beans//ns:bean" );// 创建//ns:beans//ns:bean查询路径
xpath.setNamespaceURIs(nsMap); // 设置命名空间
List<Element> eles = xpath.selectNodes(doc); // 取得文档下所有节点
for (Element element : eles) {
String id = element.attributeValue( "id" );
String cn = element.attributeValue( "class" );
//自定义实体bean,保存配置文件中id和class
MyBeans beans = new MyBeans(id, cn);
beanlist.add(beans);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getBean(String beanId) {
return beanMap.get(beanId);
}
|
6.实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.mooing.service;
public class MyBeans {
private String id;
private String className;
public MyBeans(String id, String className) {
this .id = id;
this .className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this .id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this .className = className;
}
}
|
7.测试
1
2
3
|
MyClassPathXmlApplicationContext ctx = new MyClassPathXmlApplicationContext( "spring.xml" );
MyService myService = (MyService) ctx.getBean( "myService" );
myService.save();
|
小结一下
自定义代码同样可以得到使用spring容器实例化的效果,也就是说,实际spring实例化管理bean时,也是经过两大步:
第一:服务启动解析配置文件,并保存配置文件中的元素;
第二:实例化所有元素,并提供获取实例方法。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/neweastsun/article/details/80464893