Spring6学习技术|IoC|手写IoC

学习材料

尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解)

有关反射的知识回顾

IoC是基于反射机制实现的。

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。

要想解剖一个类,必须先要获取到该类的Class对象。而剖析一个类或用反射解决具体的问题就是使用相关API(1)java.lang.Class(2)java.lang.reflect,所以,Class对象是反射的根源

具体要掌握的操作就是如何获取class(三种方法),如何获取构造器及创建对象,如何获取属性,如何获取方法并执行。(这里注意public和private的不同操作)。

package com.zy.reflect;

import org.testng.annotations.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestCar {
   
    @Test
    public void test01() throws Exception {
   
        //获取class的方法
//        Car car = new Car();
//        Class clazz1 = car.getClass();

        Class clazz2 = Car.class;

        Class clazz3 = Class.forName("com.zy.reflect.Car");

        Constructor[] constructors = clazz3.getDeclaredConstructors();
        for(Constructor con:constructors){
   
            if(con.getParameterCount()==3){
   
                con.setAccessible(true);
                Car car = (Car) con.newInstance("奔驰", 1, "黑色");
//                System.out.println(car);
            }
        }
        //或者直接获取
        Constructor c2 = clazz3.getDeclaredConstructor(String.class, Integer.class, String.class);
        c2.setAccessible(true);
        Car car2 = (Car)c2.newInstance("捷达", 15, "白色");
        System.out.println(car2);

    }
    @Test
    public void test02() throws Exception {
   

        Class clazz3 = Class.forName("com.zy.reflect.Car");
        Car car = (Car)clazz3.getConstructor().newInstance();
        Field[] fields = clazz3.getDeclaredFields();
        for (Field field:fields) {
   
            if(field.getName().equals("name")) {
   
                //设置允许访问
                field.setAccessible(true);
                field.set(car,"五菱宏光");//这里需要有对应的对象。
                System.out.println(car);
            }
            System.out.println(field.getName());

        }


    }
    @Test
    public void test03() throws Exception {
   

        Class clazz3 = Class.forName("com.zy.reflect.Car");
        Car car = (Car)clazz3.getConstructor().newInstance();
        Method[] methods = clazz3.getDeclaredMethods();
        for (Method method:methods) {
   

            //执行方法 toString
            if(method.getName().equals("toString")) {
   
                String invoke = (String)method.invoke(car);
                System.out.println("toString执行了:"+invoke);
            }
            if(method.getName().equals("run")) {
   
                //设置允许访问
                method.setAccessible(true);
                method.invoke(car);//这里需要有对应的对象。
                System.out.println(car);
            }
        }
    }
}

手写IoC

实现的思路设计
在这里插入图片描述
环境框架
在这里插入图片描述

第一二步手打过很多次了,没什么难度。
第三步:
创建Annotation文件,与接口之类的类似。不同在于有元注解需要考虑(注解面向的范围)Bean是创建类,Di注入

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

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

第四步:要了解这一步要干嘛,需要从需求出发。
需求如下:即输入一个com.zy。我要组织得到一个Map集合,创建好所有标注注解Bean的类,与Di注入。getBean用于利用class信息返回Map内的元素。

public class TestUser {
   
    public static void main(String[] args) {
   
        ApplicationContext context = new AnnotationApplicationContext("com.zy");
        UserService bean = (UserService)context.getBean(UserService.class);
        bean.add();

    }
}

如何实现创建Map(主要学习的是如何遍历文件,如何扫描注解)

private Map<Class, Object> beanFactory = new HashMap<>();
    private static String rootPath;
    @Override
    public Object getBean(Class clazz) {
   
        return beanFactory.get(clazz);
    }
public AnnotationApplicationContext(String basePackage) {
   
        //如何根据包的路径,设置扫描规则
        try {
   
            String packageDirName = basePackage.replaceAll("\\.", "\\\\");
            Enumeration<URL> dirs =Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {
   
                URL url = dirs.nextElement();
                String filePath = URLDecoder.decode(url.getFile(),"utf-8");
//                System.out.println(filePath);
                //包扫描
                rootPath = filePath.substring(0, filePath.length()-packageDirName.length());
                loadBean(new File(filePath));
            }
        } catch (Exception e) {
   
            throw new RuntimeException(e);
        }
        //属性注入
        loadDi();

    }

    private void loadBean(File file) throws Exception {
   
        //1.当前FIle是否是文件夹
        if (file.isDirectory()){
   
            //2.是文件夹的话,获取所有内容
            File[] childrenFiles = file.listFiles();
            //3.判断内容是否为空
            if (childrenFiles == null || childrenFiles.length==0){
   
                return;
            }
            //4.遍历所有内容
            for (File child:childrenFiles){
   
                //1.还是文件夹就递归
                if (child.isDirectory()){
   
                    loadBean(child);
                }else {
   
                    //是文件,获取完整的类路径
                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length()-1);
                    //是不是class文件
                    if (pathWithClass.contains(".class")){
   
                        String allName = pathWithClass.replaceAll("\\\\", "\\.").replace(".class", "");
                        //判断类中有没有@Bean注解
                        Class<?> clazz = Class.forName(allName);
                        if (!clazz.isInterface()){
   
                            Bean annotation = (Bean)clazz.getAnnotation(Bean.class);
                            if (annotation!=null){
   
                                Object instance = clazz.getConstructor().newInstance();
                                if (clazz.getInterfaces().length>0){
   
                                    beanFactory.put(clazz.getInterfaces()[0], instance);
                                }else{
   
                                    beanFactory.put(clazz, instance);
                                }
                            }

                        }

                    }


                }

            }


        }

    }
    private void loadDi(){
   
        //实例化对象在beanFactory的map
        //1 遍历beanFactory的map
        Set<Map.Entry<Class, Object>> entries = beanFactory.entrySet();
        for(Map.Entry<Class, Object> entry:entries){
   
            //2 获取map的每个对象value,每个对象属性获取到
            Object obj = entry.getValue();
            Class clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            //3 遍历得到每个对象属性数组,得到每个属性
            for(Field field:fields){
   
                //4 判断属性上面是都有@Di注解
                Di annotation = field.getAnnotation(Di.class);
                //5 如果有@Di注解,把对象进行设置(注入)
                if (annotation!=null){
   
                    field.setAccessible(true);
                    //这一步什么??filed这个属性的类型field.getType() beanFactory.get()得到对应的对象。
                    try {
   
                        field.set(obj, beanFactory.get(field.getType()));
                    } catch (IllegalAccessException e) {
   
                        throw new RuntimeException(e);
                    }
                }
            
        }

    }

相关推荐

  1. 简易版Spring IOC容器02【学习

    2024-02-22 07:06:04       16 阅读
  2. 简易版Spring IOC容器04【学习

    2024-02-22 07:06:04       25 阅读
  3. 简易版Spring IOC容器05【学习

    2024-02-22 07:06:04       24 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-22 07:06:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-22 07:06:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-22 07:06:04       87 阅读
  4. Python语言-面向对象

    2024-02-22 07:06:04       96 阅读

热门阅读

  1. android放松眼睛提醒功能

    2024-02-22 07:06:04       60 阅读
  2. 通过Django实现获取当前时间

    2024-02-22 07:06:04       53 阅读
  3. 基于python+django+vue.js开发的停车管理系统

    2024-02-22 07:06:04       49 阅读
  4. 物联网土壤传感器简介

    2024-02-22 07:06:04       54 阅读
  5. serverless是什么?

    2024-02-22 07:06:04       56 阅读
  6. C++知识点总结(19):高级贪心算法

    2024-02-22 07:06:04       43 阅读
  7. CSE13S c++ programme

    2024-02-22 07:06:04       42 阅读
  8. 学习Android的第十七天

    2024-02-22 07:06:04       39 阅读