通过反射实现依赖注入DI

依赖注入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]
_________________ *_*______
____ ____ ____
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值