本文介绍: 3.4.2 创建bean实例(IoC)在程序运行时,执行bean工厂初始化。3.4.1 扫描指定包下的所有类。

3.4 my spring bean工厂(IoC、DI)

  • 加载类
  • 解析类
  • 获得类

3.4.0 分析

在这里插入图片描述
3.4.1 扫描指定包下的所有类
在这里插入图片描述

package com.czxy.bean;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


public class MyBeanFactory {

    private static String classpath = new File(MyBeanFactory.class.getClassLoader().getResource("").getPath()).getPath();

    /**
     * 初始化方法
     * @param packageName
     */
    public static void init(String packageName) {
        //1 扫描 指定包 下面的所有内容(接口、类)
        // 1.1 获得 指定包 所在的位置,以文件File形式
        File packageFile = packageToFile(packageName);
        // 1.2 根据 包的位置 获得所有的类
        List<String> classNameList = getAllClassName(packageFile);
        System.out.println(classNameList);

        //2 处理类
    }


    /**
     * com.czxy --> com/czxy
     * @param packageName
     * @return
     */
    private static File packageToFile(String packageName) {
        return new File(classpath , packageName.replace(".", "/"));
    }

    /**
     * 获得指定包所有内容,如果是类
     * @param dir
     * @return
     */
    private static List<String> getAllClassName(File dir) {
        List<String> list = new ArrayList<>();
        if(dir == null) {
            return list;
        }
        for(File file: Objects.requireNonNull(dir.listFiles())) {
            if(file.isFile()) {
                list.add(pathToClassName(file.getPath()));
            } else {
                List<String> subList = getAllClassName(file);
                list.addAll(subList);
            }
        }
        return list;
    }

    /**
     *
     * @param path
     * @return A.B.C
     */
    private static String pathToClassName(String path) {
        // 取消前缀
        String newPath = path.replace(classpath + "\", "");
        if(newPath.endsWith(".class")) {
            //处理类
            String tempPath = newPath.replace("\", ".");
            return tempPath.substring(0, tempPath.length() - 6);
        } else {
            return newPath;
        }
    }
}

在程序运行时,执行bean工厂初始化
在这里插入图片描述
3.4.2 创建bean实例(IoC)
在这里插入图片描述
Bean工厂

在这里插入图片描述
*

package com.czxy.bean;

import com.czxy.annotation.MyMapper;
import com.czxy.annotation.MyRestController;
import com.czxy.annotation.MyService;
import com.czxy.boot.MybatisHandler;

import java.io.File;
import java.lang.reflect.Proxy;
import java.util.*;


public class MyBeanFactory {

    private static String classpath = new File(MyBeanFactory.class.getClassLoader().getResource("").getPath()).getPath();

    private static Map<Class, Object> objectMap = new HashMap<>();

    /**
     * 初始化方法
     * @param packageName
     */
    public static void init(String packageName) {
        try {
            //1 扫描 指定包 下面的所有内容(接口、类)
            // 1.1 获得 指定包 所在的位置,以文件File形式
            File packageFile = packageToFile(packageName);
            // 1.2 根据 包的位置 获得所有的类
            List<String> classNameList = getAllClassName(packageFile);

            //2 处理类:创建实例(IoC)
            // 2.1 遍历所有的类文件
            for(String className: classNameList) {
                // 2.2 获得类对应Class对象
                Class beanClass = Class.forName(className);

                // 2.3 根据注解创建实例
                // 2.3.1 如果有@RestController,创建controller
                boolean isController = beanClass.isAnnotationPresent(MyRestController.class);
                if(isController) {
                    // 直接创建对象
                    objectMap.put(beanClass, beanClass.newInstance());

                }
                // 2.3.2 如果有@Service,创建Service,需要获得接口
                boolean isService = beanClass.isAnnotationPresent(MyService.class);
                if(isService) {
                    // 如果有接口,接口-->实现类。 如果没有接口, 实现类-->实现类
                    Class[] interfaces = beanClass.getInterfaces();
                    if(interfaces.length == 0) {
                        // 没有接口
                        objectMap.put(beanClass, beanClass.newInstance());
                    } else {
                        // 有接口
                        objectMap.put(interfaces[0], beanClass.newInstance());
                    }

                }
                // 2.3.3 如果有@Mapper,创建代理
                boolean isMapper = beanClass.isAnnotationPresent(MyMapper.class);
                if(isMapper) {
                    // 创建Map对应的代理类
                    // 1) 参数
                    // 1.1) 类加载器
                    ClassLoader loader = MyBeanFactory.class.getClassLoader();
                    // 1.2) 接口们
                    Class[] interfaces = new Class[] {beanClass};
                    // 1.3) 处理类
                    MybatisHandler mybatisHandler = new MybatisHandler(beanClass);
                    // 2) 工具创建
                    objectMap.put(beanClass, Proxy.newProxyInstance(loader, interfaces, mybatisHandler));

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

        System.out.println(objectMap);
    }


    /**
     * com.czxy --> com/czxy
     * @param packageName
     * @return
     */
    private static File packageToFile(String packageName) {
        return new File(classpath , packageName.replace(".", "/"));
    }

    /**
     * 获得指定包所有内容,如果是类
     * @param dir
     * @return
     */
    private static List<String> getAllClassName(File dir) {
        List<String> list = new ArrayList<>();
        if(dir == null) {
            return list;
        }
        for(File file: Objects.requireNonNull(dir.listFiles())) {
            if(file.isFile()) {
                list.add(pathToClassName(file.getPath()));
            } else {
                List<String> subList = getAllClassName(file);
                list.addAll(subList);
            }
        }
        return list;
    }

    /**
     *
     * @param path
     * @return A.B.C
     */
    private static String pathToClassName(String path) {
        // 取消前缀
        String newPath = path.replace(classpath + "\", "");
        if(newPath.endsWith(".class")) {
            //处理类
            String tempPath = newPath.replace("\", ".");
            return tempPath.substring(0, tempPath.length() - 6);
        } else {
            return newPath;
        }
    }
}

  • 代理类处理类

    package com.czxy.boot;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    
    public class MybatisHandler implements InvocationHandler {
        private Class beanClass;
        public MybatisHandler(Class beanClass) {
            this.beanClass = beanClass;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("代理类的处理类执行了");
            //1 获得方法名
            String methodName = method.getName();
            //2 处理 toString 方法
            if("toString".equals(methodName)) {
                return "myProxy";
            }
            return null;
        }
    }
    
    

3.4.3 依赖关系

在这里插入图片描述
package com.czxy.bean;

import com.czxy.annotation.MyMapper;
import com.czxy.annotation.MyRestController;
import com.czxy.annotation.MyService;
import com.czxy.boot.MybatisHandler;

import javax.annotation.Resource;
import javax.annotation.Resources;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.*;

public class MyBeanFactory {

private static String classpath = new File(MyBeanFactory.class.getClassLoader().getResource("").getPath()).getPath();

private static Map<Class, Object> objectMap = new HashMap<>();

/**
 * 初始化方法
 * @param packageName
 */
public static void init(String packageName) {
    try {
        //1 扫描 指定包 下面的所有内容(接口、类)
        // 1.1 获得 指定包 所在的位置,以文件File形式
        File packageFile = packageToFile(packageName);
        // 1.2 根据 包的位置 获得所有的类
        List<String> classNameList = getAllClassName(packageFile);

        //2 处理类:创建实例(IoC)
        // 2.1 遍历所有的类文件
        for(String className: classNameList) {
            // 2.2 获得类对应Class对象
            Class beanClass = Class.forName(className);

            // 2.3 根据注解创建实例
            // 2.3.1 如果有@RestController,创建controller
            boolean isController = beanClass.isAnnotationPresent(MyRestController.class);
            if(isController) {
                // 直接创建对象
                objectMap.put(beanClass, beanClass.newInstance());
            }
            // 2.3.2 如果有@Service,创建Service,需要获得接口
            boolean isService = beanClass.isAnnotationPresent(MyService.class);
            if(isService) {
                // 如果有接口,接口-->实现类。 如果没有接口, 实现类-->实现类
                Class[] interfaces = beanClass.getInterfaces();
                if(interfaces.length == 0) {
                    // 没有接口
                    objectMap.put(beanClass, beanClass.newInstance());
                } else {
                    // 有接口
                    objectMap.put(interfaces[0], beanClass.newInstance());
                }
            }
            // 2.3.3 如果有@Mapper,创建代理
            boolean isMapper = beanClass.isAnnotationPresent(MyMapper.class);
            if(isMapper) {
                // 创建Map对应的代理类
                // 1) 参数
                // 1.1) 类加载器
                ClassLoader loader = MyBeanFactory.class.getClassLoader();
                // 1.2) 接口们
                Class[] interfaces = new Class[] {beanClass};
                // 1.3) 处理类
                MybatisHandler mybatisHandler = new MybatisHandler(beanClass);
                // 2) 工具创建
                objectMap.put(beanClass, Proxy.newProxyInstance(loader, interfaces, mybatisHandler));

            }
        }

        //3 处理类:依赖注入
        // 2.1 变量ObjectMap
        for(Map.Entry<Class, Object> entry : objectMap.entrySet()) {
            // 获得map中对象对应的Class
            Class beanClass = entry.getValue().getClass();
            // 2.2 获得所有的字段(含私有)
            Field[] fieldList = beanClass.getDeclaredFields();
            // 2.3 遍历字段
            for(Field field: fieldList) {
                // 2.4 判断字段是否有@Resource
                boolean isResource = field.isAnnotationPresent(Resource.class);
                if(isResource) {
                    // 2.5 如果有注解,获得类型
                    Class<?> fieldType = field.getType();
                    // 2.6 根据类型,从objectMap获得对应的对象
                    Object obj = objectMap.get(fieldType);
                    // 2.7 设置访问权限
                    field.setAccessible(true);
                    // 2.8 设置对象
                    field.set(entry.getValue(), obj);
                }
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    System.out.println(objectMap);
}


/**
 * com.czxy --> com/czxy
 * @param packageName
 * @return
 */
private static File packageToFile(String packageName) {
    return new File(classpath , packageName.replace(".", "/"));
}

/**
 * 获得指定包所有内容,如果是类
 * @param dir
 * @return
 */
private static List<String> getAllClassName(File dir) {
    List<String> list = new ArrayList<>();
    if(dir == null) {
        return list;
    }
    for(File file: Objects.requireNonNull(dir.listFiles())) {
        if(file.isFile()) {
            list.add(pathToClassName(file.getPath()));
        } else {
            List<String> subList = getAllClassName(file);
            list.addAll(subList);
        }
    }
    return list;
}

/**
 *
 * @param path
 * @return A.B.C
 */
private static String pathToClassName(String path) {
    // 取消前缀
    String newPath = path.replace(classpath + "\", "");
    if(newPath.endsWith(".class")) {
        //处理类
        String tempPath = newPath.replace("\", ".");
        return tempPath.substring(0, tempPath.length() - 6);
    } else {
        return newPath;
    }
}

}

原文地址:https://blog.csdn.net/qiuyeyyy/article/details/135878880

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_63807.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注