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;
}
}
}