MichaelFreeman

模拟spring ioc

属性文件工具类

如何从配置文件中获取我们定义的参数

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
public final class PropsUtil {

private static final Logger LOGGER = LoggerFactory.getLogger(PropsUtil.class);

/**
* 加载属性文件
*/
public static Properties loadProps(String fileName) {
Properties props = null;
InputStream is = null;
try {
is = ClassUtil.getClassLoader().getResourceAsStream(fileName);
if (is == null) {
throw new FileNotFoundException(fileName + " file is not found");
}
props = new Properties();
props.load(is);
} catch (IOException e) {
LOGGER.error("load properties file failure", e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
LOGGER.error("close input stream failure", e);
}
}
}
return props;
}
}

配置中心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface ConfigConstant {

String CONFIG_FILE = "smart.properties";

String JDBC_DRIVER = "smart.framework.jdbc.driver";
String JDBC_URL = "smart.framework.jdbc.url";
String JDBC_USERNAME = "smart.framework.jdbc.username";
String JDBC_PASSWORD = "smart.framework.jdbc.password";

String APP_BASE_PACKAGE = "smart.framework.app.base_package";
String APP_JSP_PATH = "smart.framework.app.jsp_path";
String APP_ASSET_PATH = "smart.framework.app.asset_path";
String APP_UPLOAD_LIMIT = "smart.framework.app.upload_limit";
}

我们提供一个配置中心的助手类,用来加载上面的配置

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public final class ConfigHelper {

private static final Properties CONFIG_PROPS = PropsUtil.loadProps(ConfigConstant.CONFIG_FILE);

/**
* 获取 JDBC 驱动
*/
public static String getJdbcDriver() {
return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_DRIVER);
}

/**
* 获取 JDBC URL
*/
public static String getJdbcUrl() {
return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_URL);
}

/**
* 获取 JDBC 用户名
*/
public static String getJdbcUsername() {
return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_USERNAME);
}

/**
* 获取 JDBC 密码
*/
public static String getJdbcPassword() {
return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_PASSWORD);
}

/**
* 获取应用基础包名
*/
public static String getAppBasePackage() {
return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_BASE_PACKAGE);
}

/**
* 获取应用 JSP 路径
*/
public static String getAppJspPath() {
return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_JSP_PATH, "/WEB-INF/view/");
}

/**
* 获取应用静态资源路径
*/
public static String getAppAssetPath() {
return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_ASSET_PATH, "/asset/");
}

/**
* 获取应用文件上传限制
*/
public static int getAppUploadLimit() {
return PropsUtil.getInt(CONFIG_PROPS, ConfigConstant.APP_UPLOAD_LIMIT, 10);
}

/**
* 根据属性名获取 String 类型的属性值
*/
public static String getString(String key) {
return PropsUtil.getString(CONFIG_PROPS, key);
}

/**
* 根据属性名获取 int 类型的属性值
*/
public static int getInt(String key) {
return PropsUtil.getInt(CONFIG_PROPS, key);
}

/**
* 根据属性名获取 boolean 类型的属性值
*/
public static boolean getBoolean(String key) {
return PropsUtil.getBoolean(CONFIG_PROPS, key);
}
}

类加载器

获取类加载器,加载类以及扫描包

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
public final class ClassUtil {

private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);

/**
* 获取类加载器
*/
public static ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}

/**
* 加载类
*/
public static Class<?> loadClass(String className, boolean isInitialized) {
Class<?> cls;
try {
cls = Class.forName(className, isInitialized, getClassLoader());
} catch (ClassNotFoundException e) {
LOGGER.error("load class failure", e);
throw new RuntimeException(e);
}
return cls;
}

/**
* 加载类(默认将初始化类)
*/
public static Class<?> loadClass(String className) {
return loadClass(className, true);
}

/**
* 获取指定包名下的所有类
*/
public static Set<Class<?>> getClassSet(String packageName) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
try {
Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
String packagePath = url.getPath().replaceAll("%20", " ");
addClass(classSet, packagePath, packageName);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
if (jarURLConnection != null) {
JarFile jarFile = jarURLConnection.getJarFile();
if (jarFile != null) {
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarEntryName = jarEntry.getName();
if (jarEntryName.endsWith(".class")) {
String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
doAddClass(classSet, className);
}
}
}
}
}
}
}
} catch (Exception e) {
LOGGER.error("get class set failure", e);
throw new RuntimeException(e);
}
return classSet;
}

private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) {
File[] files = new File(packagePath).listFiles(new FileFilter() {
public boolean accept(File file) {
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
}
});
for (File file : files) {
String fileName = file.getName();
if (file.isFile()) {
String className = fileName.substring(0, fileName.lastIndexOf("."));
if (StringUtil.isNotEmpty(packageName)) {
className = packageName + "." + className;
}
doAddClass(classSet, className);
} else {
String subPackagePath = fileName;
if (StringUtil.isNotEmpty(packagePath)) {
subPackagePath = packagePath + "/" + subPackagePath;
}
String subPackageName = fileName;
if (StringUtil.isNotEmpty(packageName)) {
subPackageName = packageName + "." + subPackageName;
}
addClass(classSet, subPackagePath, subPackageName);
}
}
}

private static void doAddClass(Set<Class<?>> classSet, String className) {
Class<?> cls = loadClass(className, false);
classSet.add(cls);
}
}

定义注解

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
/**
* 控制器注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
}

/**
* 服务类注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}

/**
* Action 方法注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Action {

/**
* 请求类型与路径
*/
String value();
}

/**
* 依赖注入注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
}

类操作管理

获取包下所有的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
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public final class ClassHelper {

/**
* 定义类集合(用于存放所加载的类)
*/
private static final Set<Class<?>> CLASS_SET;

static {
String basePackage = ConfigHelper.getAppBasePackage();
CLASS_SET = ClassUtil.getClassSet(basePackage);
}

/**
* 获取应用包名下的所有类
*/
public static Set<Class<?>> getClassSet() {
return CLASS_SET;
}

/**
* 获取应用包名下所有 Service 类
*/
public static Set<Class<?>> getServiceClassSet() {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (Class<?> cls : CLASS_SET) {
if (cls.isAnnotationPresent(Service.class)) {
classSet.add(cls);
}
}
return classSet;
}

/**
* 获取应用包名下所有 Controller 类
*/
public static Set<Class<?>> getControllerClassSet() {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (Class<?> cls : CLASS_SET) {
if (cls.isAnnotationPresent(Controller.class)) {
classSet.add(cls);
}
}
return classSet;
}

/**
* 获取应用包名下所有 Bean 类(包括:Service、Controller 等)
*/
public static Set<Class<?>> getBeanClassSet() {
Set<Class<?>> beanClassSet = new HashSet<Class<?>>();
beanClassSet.addAll(getServiceClassSet());
beanClassSet.addAll(getControllerClassSet());
return beanClassSet;
}

/**
* 获取应用包名下某父类(或接口)的所有子类(或实现类)
*/
public static Set<Class<?>> getClassSetBySuper(Class<?> superClass) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (Class<?> cls : CLASS_SET) {
if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)) {
classSet.add(cls);
}
}
return classSet;
}

/**
* 获取应用包名下带有某注解的所有类
*/
public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotationClass) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (Class<?> cls : CLASS_SET) {
if (cls.isAnnotationPresent(annotationClass)) {
classSet.add(cls);
}
}
return classSet;
}
}

Bean管理

维护一个Map,key是class,value是class对应的实例

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
public final class BeanHelper {

private static final Map<Class<?>, Object> BEAN_MAP = new HashMap<Class<?>, Object>();

static {
Set<Class<?>> beanClassSet = ClassHelper.getBeanClassSet();
for (Class<?> beanClass : beanClassSet) {
Object obj = ReflectionUtil.newInstance(beanClass);
BEAN_MAP.put(beanClass, obj);
}
}

/**
* 获取 Bean 映射
*/
public static Map<Class<?>, Object> getBeanMap() {
return BEAN_MAP;
}

/**
* 获取 Bean 实例
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(Class<T> cls) {
if (!BEAN_MAP.containsKey(cls)) {
throw new RuntimeException("can not get bean by class: " + cls);
}
return (T) BEAN_MAP.get(cls);
}

/**
* 设置 Bean 实例
*/
public static void setBean(Class<?> cls, Object obj) {
BEAN_MAP.put(cls, obj);
}
}

依赖注入

对于控制器Controller,可以将服务层Service注入其中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public final class IocHelper {
static {
Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
if (CollectionUtil.isNotEmpty(beanMap)) {
for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) {
Class<?> beanClass = beanEntry.getKey();
Object beanInstance = beanEntry.getValue();
Field[] beanFields = beanClass.getDeclaredFields();
if (ArrayUtil.isNotEmpty(beanFields)) {
for (Field beanField : beanFields) {
if (beanField.isAnnotationPresent(Inject.class)) {
Class<?> beanFieldClass = beanField.getType();
Object beanFieldInstance = beanMap.get(beanFieldClass);
if (beanFieldInstance != null) {
ReflectionUtil.setField(beanInstance, beanField, beanFieldInstance);
}
}
}
}
}
}
}
}

控制器管理

维护一个Map,key为请求,value为对应的处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 封装请求信息
*/
public class Request {

/**
* 请求方法
*/
private String requestMethod;

/**
* 请求路径
*/
private String requestPath;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 封装 Action 信息
*/
public class Handler {

/**
* Controller 类
*/
private Class<?> controllerClass;

/**
* Action 方法
*/
private Method actionMethod;
}
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
/**
* 控制器助手类
*/
public final class ControllerHelper {

private static final Map<Request, Handler> ACTION_MAP = new HashMap<Request, Handler>();

static {
Set<Class<?>> controllerClassSet = ClassHelper.getControllerClassSet();
if (CollectionUtil.isNotEmpty(controllerClassSet)) {
for (Class<?> controllerClass : controllerClassSet) {
Method[] methods = controllerClass.getDeclaredMethods();
if (ArrayUtil.isNotEmpty(methods)) {
for (Method method : methods) {
if (method.isAnnotationPresent(Action.class)) {
Action action = method.getAnnotation(Action.class);
String mapping = action.value();
if (mapping.matches("\\w+:/\\w*")) {
String[] array = mapping.split(":");
if (ArrayUtil.isNotEmpty(array) && array.length == 2) {
String requestMethod = array[0];
String requestPath = array[1];
Request request = new Request(requestMethod, requestPath);
Handler handler = new Handler(controllerClass, method);
ACTION_MAP.put(request, handler);
}
}
}
}
}
}
}
}

/**
* 获取 Handler
*/
public static Handler getHandler(String requestMethod, String requestPath) {
Request request = new Request(requestMethod, requestPath);
return ACTION_MAP.get(request);
}
}

核心类-请求转发器

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

@Override
public void init(ServletConfig servletConfig) throws ServletException {
HelperLoader.init();

ServletContext servletContext = servletConfig.getServletContext();

registerServlet(servletContext);

UploadHelper.init(servletContext);
}

private void registerServlet(ServletContext servletContext) {
ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
jspServlet.addMapping("/index.jsp");
jspServlet.addMapping(ConfigHelper.getAppJspPath() + "*");

ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
defaultServlet.addMapping("/favicon.ico");
defaultServlet.addMapping(ConfigHelper.getAppAssetPath() + "*");
}

@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletHelper.init(request, response);
try {
String requestMethod = request.getMethod().toLowerCase();
String requestPath = request.getPathInfo();
Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
if (handler != null) {
Class<?> controllerClass = handler.getControllerClass();
Object controllerBean = BeanHelper.getBean(controllerClass);

Param param;
if (UploadHelper.isMultipart(request)) {
param = UploadHelper.createParam(request);
} else {
param = RequestHelper.createParam(request);
}

Object result;
Method actionMethod = handler.getActionMethod();
if (param.isEmpty()) {
result = ReflectionUtil.invokeMethod(controllerBean, actionMethod);
} else {
result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
}

if (result instanceof View) {
handleViewResult((View) result, request, response);
} else if (result instanceof Data) {
handleDataResult((Data) result, response);
}
}
} finally {
ServletHelper.destroy();
}
}

private void handleViewResult(View view, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String path = view.getPath();
if (StringUtil.isNotEmpty(path)) {
if (path.startsWith("/")) {
response.sendRedirect(request.getContextPath() + path);
} else {
Map<String, Object> model = view.getModel();
for (Map.Entry<String, Object> entry : model.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}
request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request, response);
}
}
}

private void handleDataResult(Data data, HttpServletResponse response) throws IOException {
Object model = data.getModel();
if (model != null) {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
String json = JsonUtil.toJson(model);
writer.write(json);
writer.flush();
writer.close();
}
}
}