深入spring,学习注解怎么工作的。类加载器的玩法,内嵌tomcat是怎么一回事。通过细节了解之前从来没关注过的点。
先从ioc聊起
控制反转:对象不是我们new的,对象的属性也不是我们注入的。 依赖注入:属性是框架帮我们注入的。
package com.obsidian.demo.test;
/**
* 用常用的代码 进入分析
* 如果没有Spring....
* @author huoyun
* @date 2019/7/13-11:43
*/
public class UserController {
/**
* 如果没有Spring IOC
* 这就得 开始new对象了。
*/
private UserService userService;
}
如果是@AutoWried 是不需要写set方法的。这是通过getDeclaredFields拿到private属性进行注入。 field.setAccessible(true);是能给private属性赋值的原因
/**
* 手写IOC
* 这种方式 通过getDeclaredFields 能够拿到private属性 不走set方法 进行属性注入
* 这也是@AutoWried 的手段
*/
@Test
public void IOCTest() throws Exception {
// jdk 1.9这么写deprecate 需要去拿 构造器
UserController userController = UserController.class.newInstance();
UserService userService = UserService.class.newInstance();
// 能拿到各种修饰符的
// Field[] declaredFields = UserController.class.getDeclaredFields();
// Arrays.stream(declaredFields).forEach(System.out::println);//private com.obsidian.demo.test.UserService com.obsidian.demo.test.UserController.userService
// 简单来说 已经知道属性是啥了 直接根据名字拿
Field field = UserController.class.getDeclaredField("userService");
System.out.println("userService:" + field);//userService:private com.obsidian.demo.test.UserService com.obsidian.demo.test.UserController.userService
// false 是不能给private的属性赋值的 改成true
field.setAccessible(true);
// 第一个参数 是给那个类的field 赋值 第二个参数 是value
field.set(userController, userService);
// 这时候发现已经注入进去了
System.out.println(ToStringBuilder.reflectionToString(userController));
}
还可以拿到field的名字首字母大写然后在前面拼接上set,invoke这个方法。个人觉得无意义上面的才是用的最多的。 自己写了一个@Autowired 来实现给带@Autowired的属性进行注入
@Test
public void IOCTestWithAnnotation() {
UserController userController = new UserController();
// all fields
Field[] declaredFields = UserController.class.getDeclaredFields();
Arrays.stream(declaredFields).forEach(item -> {
// 判断 有没有Autowired注解
if (item.isAnnotationPresent(Autowired.class)) {
// 拿到field的类型
Class<?> type = item.getType();
try {
// 根据拿出的类型进行实例化
Object instance = type.newInstance();
// 可以对private进行访问 然后赋值
item.setAccessible(true);
item.set(userController, instance);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
});
System.out.println(ToStringBuilder.reflectionToString(userController));
}