一、实现依赖注入
1.1、.一个问题:在@Controller中定义Service成员变量,然后在Controller的Action方法中调用Service成员变量的方法,如何实现Service成员变量呢?可以通过@Inject注解来实现Controller中的Service实例化。
1.2、一种方式:通过BeanHelper获取所有BeanMap(记录了类与对象的映射关系)。然后遍历这个映射关系,分别取出Bean类与Bean实例,进而通过反射获取类中的成员变量。继续遍历这些成员变量,在循环中判断当前成员变量是否带有@Inject注解,若是带有该注解,则从BeanMap中根据Bean类取出Bean实例。最后通过Reflection#setFiled方法来修改当前成员变量的值。
1.3、编写IocHelper.java类来完成这件事情。编写好了IocHelper.java这个依赖注入的类,通过谁来加载呢?在什么时候加载呢?其实当IocHelper.java这个类被加载的时候,就会加载它的静态代码块。所以我们可以找一个统一的地方来加载IocHelper.java这个类。
package org.smart4j.framework.helper;
import java.lang.reflect.Field;
import java.util.Map;
import org.smart4j.framework.annotation.Inject;
import org.smart4j.framework.util.ArrayUtil;
import org.smart4j.framework.util.ReflectionUtil;
/**
* 依赖注入助手类
* @author TS
*
*/
public class IocHelper {
static{
//获取所有的Map映射
Map<Class<?>,Object> beanMap = BeanHelper.getBeanMap();
//遍历BeanMap
for ( Map.Entry<Class<?>, Object> entry : beanMap.entrySet() ) {
Class<?> beanClass = entry.getKey();
Object beanInstance = entry.getValue();
//获取一个Bean定义的所有成员变量
Field[] beanFields = beanClass.getDeclaredFields();
if( ArrayUtil.isNotEmpty(beanFields) ){ //不为空
//遍历成员变量
for ( Field beanField : beanFields ) {
if( beanField.isAnnotationPresent( Inject.class ) ){ //判断是否包含@Inject注解
Class<?> beanFieldClass = beanField.getType(); //获取包含属性的Class对象
Object beanFieldInstance = beanMap.get(beanFieldClass); //通过获取的Class对象获取Class对象的实例
if( beanFieldInstance != null ){
//通过反射初始化BeanField的值
ReflectionUtil.setField( beanInstance, beanField, beanFieldInstance );
}
}
}
}
}
}
}
1.4、此时IocHelper.java管理的对象都是单例的,IocHelper.java底层还是从BeanHelper中获取BeanMap的。而BeanMap中的对象都是事先创建好并放入这个Bean容器的,因此所以对象都是单例的。
---------------------------------------summarize(总结):至此基于上层Bean容器实现了Ioc依赖注入的功能,就可以通过@Inject注解来实现依赖注入了。-----------------------------------------
来源:oschina
链接:https://my.oschina.net/u/2453485/blog/682263