獲取所有spring管理的bean
本文我們探索使用不同的方式獲取spring容器中所有bean。
IOC容器
bean是基于spring應用的基礎(chǔ),所有bean都駐留在ioc容器中,由容器負責管理bean生命周期
有兩種方式可以獲取容器中的bean:
- 使用ListableBeanFactory接口
- 使用Spring Boot Actuator
使用ListableBeanFactory接口
ListableBeanFactory接口提供了getBeanDefinitionNames() 方法,能夠返回所有定義bean的名稱。該接口被所有factory實現(xiàn),負責預加載bean定義去枚舉所有bean實例。官方文檔提供所有其子接口及其實現(xiàn)。
下面示例使用Spring Boot 構(gòu)建:
首先,我們創(chuàng)建一些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." ; } } |
我們創(chuàng)建了兩個不同的bean:
1.fooController
2.fooService
現(xiàn)在我們運行該應用。使用applicationContext 對象調(diào)用其 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提供了用于監(jiān)視應用程序統(tǒng)計信息的端點(endpoint)。除了/beans,還包括很多其他端點,官方文檔有詳細說明。
現(xiàn)在我們訪問url: http//
:/beans,如果沒有指定其他獨立管理端口,我們使用缺省端口,結(jié)果會返回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 ] } ] |
當然,結(jié)果同樣包括很多其他的bean,為了簡單起見,這里沒有列出。
小結(jié)一下
上面介紹了使用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.第一步,創(chuàng)建java project,引入spring.jar
2.創(chuàng)建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.創(chuàng)建接口MyService,只需要一個測試方法save
4.創(chuàng)建實現(xiàn)類MyServiceImpl,控制臺輸出一句話
5.創(chuàng)建一個自己的解析類MyClassPathXmlApplicationContext
主要是構(gòu)造方法中的兩步
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設(shè)置到實體中,并保持到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" );// 創(chuàng)建//ns:beans//ns:bean查詢路徑 xpath.setNamespaceURIs(nsMap); // 設(shè)置命名空間 List<Element> eles = xpath.selectNodes(doc); // 取得文檔下所有節(jié)點 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(); |
小結(jié)一下
自定義代碼同樣可以得到使用spring容器實例化的效果,也就是說,實際spring實例化管理bean時,也是經(jīng)過兩大步:
第一:服務啟動解析配置文件,并保存配置文件中的元素;
第二:實例化所有元素,并提供獲取實例方法。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/neweastsun/article/details/80464893