依赖注入DI
依赖注入简单来讲就就是对象在被创建的时候,所有依赖关系由一个调控系统管理和传递给他。也可以说,依赖被注入到对象中。Spring框架核心之一便是依赖注入,依赖注入主要实现是通过java反射,他是如何工作以及要得到的目的是什么,可以通过以下代码实战可以了解到。
如果你像了解依赖注入的详细概念可以参考以下博客
https://blog.csdn.net/sinat_21843047/article/details/80297951
注解定义
注解:Component,该注解用来描述需要容器管理的bean
package ioc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 确认bean的注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value();
}
注解:Quatifier,该注解用来描述依赖关系
package ioc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 确认需要依赖注入的bean
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Quatifier {
String value();
}
依赖实例
通过定义的注解描述,我们定义了person和hobby两个bean,并且person需要依赖hobby才能正常使用
package ioc;
@Component("person")
public class Person {
@Quatifier("hobby")
private Hobby hobby;
public void say() {
hobby.like();
}
}
package ioc;
@Component("hobby")
public class Hobby {
public void like() {
System.out.println("I love programming");
}
}
依赖注入调控系统实现核心
package ioc;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Context {
// 保存项目中所有类的全类名
private static List<String> packageNames = new ArrayList<String>();
// 所有类的实例,key是注解的值,value为类的实例
private static Map<String, Object> instanceMap = new HashMap<String, Object>();
// 构造时初始化bean
public Context() {
scanPackage("");
filterAndInstance();
ioc();
}
/**
* 扫描项目中所有class文件,将全类名放入packageNames容器管理
*
* @param sPackage 包名
*/
private void scanPackage(String sPackage) {
if (!"".equals(sPackage)) sPackage += "/";
String pathFile = this.getClass().getClassLoader().getResource(sPackage).getFile(); // 获取项目根目录
File file = new File(pathFile);
String fileList[] = file.list();
if (fileList == null) return;
for (String path : fileList) {
File eachFile = new File(pathFile + path);
if (eachFile.isDirectory()) {
scanPackage(sPackage + eachFile.getName());
} else {
if (eachFile.getName().lastIndexOf(".class") > 0) { // 记录类的绝对路径
packageNames.add(sPackage.replaceAll("/", ".")
+ eachFile.getName().replaceAll("\\.class", ""));
}
}
}
}
/**
* 实例化组建,并放入instanceMap容器中管理
* 只管理Component注解下的bean
*/
private void filterAndInstance() {
if (packageNames.isEmpty())
return;
for (String className : packageNames) {
try {
Class<?> cName = Class.forName(className);
if (cName.isAnnotationPresent(Component.class)) {
Object instance = cName.newInstance();
Component component = cName.getAnnotation(Component.class);
String key = component.value();
instanceMap.put(key, instance);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 依赖注入,根据Quatifier注解,注入相关的bean
*/
private void ioc() {
if (instanceMap.isEmpty())
return;
for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {
// 拿到类的的所有属性
Field fields[] = entry.getValue().getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);// 可访问私有属性
if (field.isAnnotationPresent(Quatifier.class)) {
Quatifier quatifier = field.getAnnotation(Quatifier.class);
String value = quatifier.value();
try {
field.set(entry.getValue(), instanceMap.get(value));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
// 根据Component注解的值获取bean
private Object getBean(String beanName) {
return instanceMap.get(beanName);
}
// 测试
public static void main(String[] args) {
Context ctx = new Context();
Person person = (Person) ctx.getBean("person");
person.say();
}
}
/*output
* I love programming
* */
从main方法测试输出I love programming测试ok,这个简单的依赖注入实现就完成了
☀>.freerme[https://blog.csdn.net/freerme]