ioc最简单的实现

ioc原理

首先明白一个概念ioc是一个容器,用来存储实例化对象的

那么可以明白一点,如何将对象放到ioc容器中,其次就是如何将对象从ioc中拿出来

类似于如下

存入ioc容器

首先我们肯定不能手动将对象put进去,我们可以像spring那样去扫描注解‘’

那么如何去扫描注解呢?

自定义注解

这个大家去自学一下

这里简单说一下

@Retention 是 Java 中的一个元注解,用于指定被它注解的注解应该保留多久。它有一个 RetentionPolicy 参数,定义了注解的生命周期,包括三个值:

  1. RetentionPolicy.SOURCE: 注解仅保留在源代码中,编译时会被忽略,不会包含在编译后的字节码中。这类注解通常用于提供给编译器做进一步的处理。

  2. RetentionPolicy.CLASS: 注解会被包含在编译后的字节码中,但在运行时无法获取。这是默认的保留策略,如果不显式指定的话。

  3. RetentionPolicy.RUNTIME: 注解会被包含在编译后的字节码中,并且可以在运行时通过反射获取。这种保留策略通常用于在运行时处理注解信息。

@Target 是 Java 中的元注解之一,用于指定注解可以应用的地方。它定义了一个 ElementType 参数,表示注解可以应用的目标元素类型。

  1. ElementType.TYPE: 表示注解可以应用在类、接口(包括注解类型)或枚举声明。

  2. ElementType.FIELD: 表示注解可以应用在字段(包括枚举常量)声明。

  3. ElementType.METHOD: 表示注解可以应用在方法声明。

自定义注解写法
元注解(元注解的作用是负责注解其他注解。 Java5.0 定义了 4 个标准的 meta-annotation 类型,它们被用来提供对其它 annotation 类型作说明。)
public @interface 注解名称{

}

定义一个自定义的注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {

}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAutowired {
}

那么好了我们定义出了注解

定义ioc容器(其实就是一个map)
rivate Map<String, Object> beans = new HashMap<>();

ok,那么开始书写autowired与component的关系

第一步: 先找到所有的带有component的类

第二步: 将其实例化并加入到map中

第三步: 基于第一步的map便利找到所有的带有autowired注解的类

第四步: 实现自动注入

下面是我写的代码偷了个懒

好了现在实现第一步

public class ClassScanner {
    public List<Class<?>> getClasses(String packageName) throws IOException {
        try{
            String path=packageName.replace(".","/");
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();//获取当前线程的类加载器
            Enumeration<URL> resources = classLoader.getResources(path);//获取类路径下的class
            List<File> dirs = new ArrayList<>();
            while (resources.hasMoreElements()) {
                URL resource = resources.nextElement();
                dirs.add(new File(resource.getFile()));
            }
            List<Class<?>> classes = new ArrayList<>();
            for (File directory : dirs) {
                classes.addAll(findClasses(directory, packageName));
            }
            return classes;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
   List<Class<?>> classes = new ArrayList<>();//初始化一个泛型List用于装载class
        if (!directory.exists()) {
            return classes;
        }
        File[] files = directory.listFiles();
        if (files == null) {
            return classes;
        }
        try{
            for (File file:files){
                if (file.isDirectory()){
                    assert !file.getName().contains(".");
                    classes.addAll(findClasses(file, packageName + "." + file.getName()));
                }else if (file.getName().endsWith(".class")) {
                    classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return classes;
    }

第二步: 将其实例化并加入到map中

注意一下createInstance方法取出的是第一个构造函数

public class SimpleIoCContainer {
    private Map<String, Object> beans = new HashMap<>();

    public void scanAndInitialize(String packageName){
        ClassScanner classScanner=new ClassScanner();
        try{
            for (Class<?> clazz:classScanner.getClasses(packageName)){
                if (clazz.isAnnotationPresent(WyComponent.class)) {
                    // 实例化类
                    Object instance = createInstance(clazz);
                    // 将实例添加到容器中
                    beans.put(clazz.getSimpleName(), instance);
                    // 进行依赖注入
                    injectDependencies(instance);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    private Object createInstance(Class<?> clazz) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        Constructor<?> constructor = clazz.getDeclaredConstructors()[0];
        Object[] args = new Object[constructor.getParameterCount()];;
        return constructor.newInstance(args);
    }

第三步

第四步

其实为了省事写到了前面

具体实现代码

 public void injectDependencies(Object instance) throws IllegalAccessException {
        Field[] fields = instance.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(WyAutowired.class)) {
                Object dependency = beans.get(field.getType().getSimpleName());
                field.setAccessible(true);//设置可访问,无论是共有还是私有
                field.set(instance, dependency);//设置属性
            }
        }
    }

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值