Spring (1) 自定义IoC之使用注解来模拟Spring IoC来实现其功能
先来了解下什么是控制反转(IoC)?
IoC 全称 Inversion of Control ,也可以称之为依赖注入 (DI)(Dependency Injection),它是Spring框架的核心技术。
平常开发写代码时,当涉及到多个对象共同完成业务逻辑时,传统的方式是用new这个关键字来创建对象,当需要更改功能时,需要更改某一个对象时,会影响到整个业务逻辑的实现,甚至导致代码都无法通过编译。而我们用IoC来代替new来创建对象时,便会降低程序的耦合性,便于维护代码,以及后期代码扩展,适用于现在企业级开发。
依赖注入实现原理:注解和反射
1.反射标准概念
Java反射机制是程序在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称之为Java语言的反射机制。
2.注解
注解可以理解为是代码的标签。
@Target 表示该注解用于什么地方,可能的值在枚举类 ElementType中
@Retention 表示在什么级别(什么状态,程序的运行状态:源码,编译,运行阶段)保存该注解信息,可选 的参数值在枚举类型RententionPolicy中
@Documented 将此注解包含在 javadoc中,它代表者此注解会被javadoc工具提取成文档
@Inherited 允许子类继承父类的注解
部分Demo:
注解部分:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface QFfield {
String value();
}
方法:
private static Map<Object,Object> map = new HashMap<>();
public static <T> T inject(Class<T> clazz){
try {
//调用clazz无参构造方法创建 t
T t = clazz.newInstance();
//获取所有属性
Field[] fields = clazz.getDeclaredFields();
//遍历属性
for(Field field:fields){
//找到自定义注解
QFfield qFfield = field.getAnnotation(QFfield.class);
if(qFfield != null){
//注解不为空,就获取注解里的值
String value = qFfield.value();
//获取属性的类型
Class<?> type = field.getType();
if(type == String.class){
//属性类型为String类型时,给属性赋值
field.set(t,value);//参数1:属性所属对象 参数2:属性的值
}else{
//当属性为引用数据类型时
Class<?> aClass = Class.forName(value);
//从map集合中以键值对的读取值
Object o = map.get(aClass);
if(o == null){
// 若 obj 为空时,重新调用inject方法去获取值(类型递归)
o = inject(aClass);
//再放到map集合里
map.put(aClass,o);
}
//给属性赋值
field.set(t,o);
}
}
}
return t;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}