反射原理手写依赖注入(注解方式)

本文详细介绍了如何使用自定义注解实现简单的依赖注入,涉及注解定义、单例模式及服务类的依赖关系展示。通过实例演示了如何在不借助Spring等框架的情况下,利用注解来管理对象创建和依赖关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

手写依赖注入(注解方式)

  • 先谈谈什么是依赖注入?
    • 依赖注入也叫DI(Dependency Injection)是对象之间的依赖关系靠某一种手段注入.可能一说到DI就不由自主的想到Spring,那又会老生常谈了:Spring是什么?很多人会说Spring是IOC和AOP(手动滑稽☻),当然这都是初学者一些回答,不能说这些回答是错的,但是再往里探究一层,像Spring的IOC容器具体是什么?Spring依赖注入默认是怎么保证单例的?
    • 对于上述问题大部分java开发也是清楚的,不论是查阅资料得知还是debug源码探究都是了解的方式,开发人员使用这些框架时,一般不通过new创建对象,而是由容器管理对象的创建,对于依赖的服务,也不需要自己管理,而是使用注解表达依赖关系。这么做的好处有很多,代码更为简单,也更为灵活.

下面手写一个简单依赖注入: 既然是注解方式那么久先定义注解:

/***
 * Description <br>
 * @author shi.yuwen <br>  
 * 普通方式注入
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SimpleInject {
}
/***
 * Description <br>
 * @author shi.yuwen <br>
 * 单例方式注入
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.TYPE})
public @interface SimpleSingleInject {

}

注解的驱动类

/**
 * <Description> <br>
 *
 * @author shi.yuwen<br>
 * @version 1.0<br>
 * @taskId: <br>
 * @createDate 2020/07/16 16:19 <br>
 * @see date20200716annotation <br>
 */
public class SimpleContainer {
    public static Map<Class<?>, Object> instances = new ConcurrentHashMap<>();
    public static <T> T getSingleInstance(Class<T> cls) {
        try {
            //判断是否走单例
            if (!cls.isAnnotationPresent(SimpleSingleInject.class)){
                return getInstance(cls);
            }
            Object obj = instances.get(cls);
            if (null != obj) {
                return (T)obj;
            }
            //使用类锁锁代码块
            synchronized (cls) {
                if (null == instances.get(cls)) {
                    obj = getInstance(cls);
                    instances.put(cls, obj);
                }

            }
            return (T)obj;
        }
        catch (Exception e) {
            throw new RuntimeException();
        }
    }

    public static<T> T getInstance (Class<T> cls){

        try {
            T obj = cls.newInstance();
            //返回本类申明的字段包括非public,不包括父类
            Field[] declaredFields = cls.getDeclaredFields();
            for (Field f : declaredFields) {
                //判断字段是否包含指定注解类型
                if (f.isAnnotationPresent(SimpleInject.class)) {
                    //判断字段是否为私有
                    if (!f.isAccessible()) {
                        f.setAccessible(true);
                    }
                    //再次递归调用赋值
                    f.set(obj, getInstance(f.getType()));
                }

            }
            return obj;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}

写三个服务类表示依赖关系:

public class ServiceA {
    @SimpleInject
    public ServiceB serviceB;
    public void callB () {
        serviceB.action();
    }
}
@SimpleSingleInject
public class ServiceB {
    @SimpleInject
    ServiceC serviceC;
    public void action () {
        serviceC.action();
    }
}
@SimpleSingleInject
public class ServiceC {
    public void action() {
        System.out.println("I am C");
    }
}

编写测试类(装载ServiceA查看是否能依赖注入ServiceB,ServiceC)

public class TestMain {

    public static void main(String[] args) {
        //ServiceA serviceA = SimpleContainer.getInstance(ServiceA.class);
        ServiceA serviceA = SimpleContainer.getSingleInstance(ServiceA.class);
        serviceA.callB();
    }
}

测试结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值