Spring:基于反射启动Spring容器

什么场景下需要反射来启动Spring容器?在 dapeng-soa 中就有这样的需求。
一般是类似于 tomcat 容器这种模式,容器本身并没有包含 spring 的代码,而是去加载含有 spring 的业务fatJar 时,才进行启动,
此时就需要使用反射启动 spring 容器。

基于反射启动Spring容器

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
package com.maple.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;

/**
* author: HuaZhe Ray
* createDate: 2018/1/2
* createTime: 16:16
*/
public class TestSpring {
public static void main(String[] args) throws Exception {
List<String> xmlPaths = new ArrayList<>();
Enumeration<URL> resources = TestSpring.class.getClassLoader().getResources("services.xml");

while (resources.hasMoreElements()) {
URL nextElement = resources.nextElement();
// not load isuwang-soa-transaction-impl
if (!nextElement.getFile().matches(".*dapeng-transaction-impl.*"))
xmlPaths.add(nextElement.toString());
}
// ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new Object[]{xmlPaths.toArray(new String[0])});
// context.start();

Class<?> appClass = TestSpring.class.getClassLoader().loadClass("org.springframework.context.support.ClassPathXmlApplicationContext");

Class<?>[] parameterTypes = new Class[]{String[].class};
//根据参数 反射构造器
Constructor<?> constructor = appClass.getConstructor(parameterTypes);


Object context = constructor.newInstance(new Object[]{xmlPaths.toArray(new String[0])});

// ApplicationContext context1 = new ClassPathXmlApplicationContext("services.xml");
// context1.getBean("testService");

Method startMethod = appClass.getMethod("start");

startMethod.invoke(context);

Method m = appClass.getMethod("getBean", String.class);

TestService service = (TestService) m.invoke(context, "testService");
service.foo();
}
}