当前位置: 首页 > news >正文

JavaEE-自定义SSM-编写核心- my spring bean工厂(IoC、DI)

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,创建controllerboolean 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;}@Overridepublic 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,创建controllerboolean 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 变量ObjectMapfor(Map.Entry<Class, Object> entry : objectMap.entrySet()) {// 获得map中对象对应的ClassClass beanClass = entry.getValue().getClass();// 2.2 获得所有的字段(含私有)Field[] fieldList = beanClass.getDeclaredFields();// 2.3 遍历字段for(Field field: fieldList) {// 2.4 判断字段是否有@Resourceboolean 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;}
}

}

相关文章:

  • MySQL库表操作 作业
  • C语言基础13
  • HarmonyOS 鸿蒙应用开发 (七、HTTP网络组件 axios 介绍及封装使用)
  • TortoiseSVN各版本汉化包下载
  • 学习使用Flask模拟接口进行测试
  • 第3章-python深度学习——(波斯美女)
  • MySQL:MVCC原理详解
  • java:实现查询MySQL数据库中的数据,并导出excel、pdf类型文档(超详细)
  • Unity 命令模式(实例详解)
  • HCIA-HarmonyOS设备开发认证-3.内核基础
  • GO——SELECT
  • 高光谱图像加载、归一化和增强(jupyter book)
  • 【JavaEE】UDP协议与TCP协议
  • 用Flask打造一个大模型智能问答WEB网站
  • 温酒读Qt:QObject中篇2 ——欲遮还羞的 QObjectPrivate
  • [NodeJS] 关于Buffer
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • CentOS7简单部署NFS
  • hadoop集群管理系统搭建规划说明
  • javascript 总结(常用工具类的封装)
  • log4j2输出到kafka
  • React中的“虫洞”——Context
  • 计算机常识 - 收藏集 - 掘金
  • 区块链将重新定义世界
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 智能合约开发环境搭建及Hello World合约
  • 【云吞铺子】性能抖动剖析(二)
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 国内开源镜像站点
  • ​低代码平台的核心价值与优势
  • # 计算机视觉入门
  • $(selector).each()和$.each()的区别
  • (Oracle)SQL优化技巧(一):分页查询
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (接口自动化)Python3操作MySQL数据库
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)Oracle存储过程编写经验和优化措施
  • .dwp和.webpart的区别
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .NET中使用Protobuffer 实现序列化和反序列化
  • @RequestMapping-占位符映射
  • [].shift.call( arguments ) 和 [].slice.call( arguments )
  • [Android]How to use FFmpeg to decode Android f...
  • [Bugku]密码???[writeup]
  • [ChromeApp]指南!让你的谷歌浏览器好用十倍!
  • [EULAR文摘] 利用蛋白组学技术开发一项蛋白评分用于预测TNFi疗效
  • [Excel]如何找到非固定空白格數列的條件數據? 以月份報價表單為例
  • [GXYCTF2019]禁止套娃