从学习Java框架之后Spring就一直是Java视野中时时刻刻存在的东西,Spring最为强大的特性就是IOC和AOP,今天先说下IOC,从刚开始对IOC懵懵懂懂到了解Spring框架,再到熟练使用Spring,到Spring框架的一些特性解读,也是经历了很长时间,不说Spring,看我们怎么来实现IOC。IOC,通俗的说是依赖注入,可能还有其他的说法,但是在日常开发中使用它就是代替开发者初始化bean,自动的创建实例对象的。
- 来个例子吧
有两个类,UserController/UserService,我们在UserController中要使用UserService的方法,应该怎嘛办呢?
- 调用的UserService方法是static的
- 创建UserService的实例,再调用方法
我们采用第二种方法来实现:
public class UserController {
private UserService userService;
public UserController(){
userService = new UserService();
}
public void sayHello(){
//调用userService的sayHello方法
userService.sayHello();
}
}
一、我们如何实现IOC
我们最终想要的结果是这样的:
public class UserController {
@Inject
private UserService userService;
public void sayHello(){
userService.sayHello();
}
}
如何实现?
- 使用一个Map<Class<?>, Object>结构的Map用来存储所有类和实例的映射关系
- 遍历Map,分别取出bean类和bean实例
- 通过反射取出类中的成员变量
- 遍历成员变量,查看是否带有inject注解(自己新建的注解)
- 若有该注解,则从Map中根据bean类取出bean实例
- 再通过反射修改当前成员变量的值
新建inject注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
}
主体方法
public final class IocHelper {
static {
//获取bean映射关系Map
Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
if (CollectionUtil.isNotEmpty(beanMap)) {
for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) {
//获取bean类
Class<?> beanClass = beanEntry.getKey();
//获取bean实例
Object beanInstance = beanEntry.getValue();
//使用反射获取成员
Field[] beanFields = beanClass.getDeclaredFields();
if (ArrayUtil.isNotEmpty(beanFields)) {
for (Field beanField : beanFields) {
//判断成员中是否又inject注解
if (beanField.isAnnotationPresent(Inject.class)) {
//在Map中找到Bean Field对应的实例
Class<?> beanFieldClass = beanField.getType();
Object beanFieldInstance = beanMap.get(beanFieldClass);
if (beanFieldInstance != null) {
//通过反射初始化bean Field的值
ReflectionUtil.setField(beanInstance, beanField, beanFieldInstance);
}
}
}
}
}
}
}
}
当然,这个类必须是在web环境下才可以运行起来,其中包含了一些其他的工具方法,没有列出来,但是我想我给出一个简单的test示例大家就理解了:
UserService
public class UserService {
public void sayHello(){
System.out.println("say hello");
}
}
UserController
public class UserController {
@Inject
private UserService userService;
public void sayHello(){
userService.sayHello();
}
}
测试方法
@Test
public void testClass() throws Exception {
Class<?> cls = Class.forName("com.sailfish.UserController", false, Thread.currentThread().getContextClassLoader());
Object o1 = cls.newInstance();
Field field = cls.getDeclaredField("userService");
Class<?> userServiceClass = field.getType();
//创建userService的实例
Object o2 = userServiceClass.newInstance();
field.set(o1, o2);
((UserController)o1).sayHello();//say hello
}
- 得到UserController的Class
- 获得UserController的实例
- 得到UserController的field:userService
- 根据Field获得UserService类
- 创建UserService实例
- 使用反射设置UserController的成员变量userService为UserService实例
- 调用UserController的sayHello方法
总结:其实有些看起来很难的知识点只是在表面看起来难,了解之后其中的原理还是不难理解,spring的Ioc实现肯定不是这么简单,但是其背后的原理还是类似的。