文章目录
极轻量级IOC简单实现
一、IOC概念引入
提起Spring,必然会提到IOC(控制反转)和AOP(面向切面编程)。今天我们简单的介绍一下IOC,并且通过代码,更加清晰的认识IOC。
控制反转(Inversion of Control,缩写为IoC)。有人就问了,谁控制谁?如何翻转?
在我们日常的程序设计当中,一个类中有多个成员,我们需要将其一个一个的new出来。若其中一个类是接口,又存在多个实现类,当需求发生变化时,我们不得不去更改源代码,尤其当代码量上去之后,牵一线动全发,这种代价使我们不愿意接受的。如果这种更改交给用户来进行配置,而不由我们(编写程序的人)去解决,那么这个问题就得到了很好的解决。
用户所需要的这些成员,都被放在了一个容器中,当用户需要时,从容器中取得该成员。举一个例子:这个容器就相当于一个婚介所,你请求你想要找的对象,这个婚介所就会按照你的要求来帮你找到这个对象。如果没有找到,就抛出异常。
对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被容器控制,所以这叫控制反转。
更详细内容查看IOC概念的简单理解.
二、IOC功能分析
-
可以自动的注入指定类的中的复杂类成员对象,通过set方法注入。
-
八大基本类型和String类型可以通过注解的value直接赋值进行注入,也可以通过bean工厂注入。若注入的类为接口,而接口实现类存在多个,可以通过value直接进行类的指定,若不指定,则随机注入
-
这些注入的bean需要被存储起来,即需要一个map<String, BeanDefinition> beanFactory
-
循环依赖问题,A需要B,B需要A,这种问题如何解决?
答曰:创建beanDefinition,存在inject成员,判断是否注入。当注入成员时,先将inject设为true,再开始真正注入
- 如何辨别一个类需要被注入?
答曰:添加==@Component注解,并且给需要注入的成员加@Autowired==注解
- 注入的时机,是直接注入还是等到用户获取这个bean的时候才进行注入
答曰:先不着急注入bean,而是等到用户需要时,在进行bean注入,懒汉模式
- 对于只有.class文件的类,无法增加==@Component注解,只能通过某个方法的返回值来获得,这时候,需要一个@bean==注解来处理
三、关于bean注解的讨论
@bean注解只作用于方法
方法的返回值是一个bean
允许方法的参数是其他bean
这里就引出来一个很严重的问题,一个带参的方法,必然依赖其他的参数才能执行,但是当进行包扫描时,这个依赖不一定会满足,可能等到下一次扫描后,依赖才满足。这里就需要当每生成一个bean后,对这些依赖关系进行动态调整。
其中,当每发现一个带参的method时,需要用一个BeanMethodDefinition来进行保存,并存储到一个集合中。存储当然是使用Map进行存储,Map<BeanMethodDefinition,HashSet>。
使用HashSet的原因是,一个BeanMethodDefinition可能会有多个未满足的参数,而HashSet是基于散列表实现的,元素没有顺序;add、remove、contains方法的时间复杂度为O(1)。
其中所有依赖满足的方法放入一个List中,List,方便后面生成所需要的bean。
我们也得再考虑一下,如何根据一个bean快速查找到一堆依赖他的BeanMethodDefinition,则需要构建另一个Map。
Map<Class<?>, List>.
四、关于接口及其实现类的讨论
当需要的类为接口时,遍历beanFactory。通过isAssignableFrom()方法进行判断。若为真,则找到
klass.isAssignableFrom(beanClass)
五、构建Bean过程图
六、具体代码
1.工具类
PackageScanner.java
public abstract class PackageScanner {
public PackageScanner() {
}
public abstract void dealClass(Class<?> klass) throws Exception;
private void scanJar(URL url) throws Exception {
JarURLConnection connection = (JarURLConnection) url.openConnection();
JarFile jarFile = connection.getJarFile();
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
continue;
}
String className = entry.getName().replace(".class", "");
className = className.replace('/', '.');
Class<?> klass = Class.forName(className);
dealClass(klass);
}
}
private void scanFile(File dir, String packageName) throws Exception {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
scanFile(file, packageName + "." + file.getName());
} else if (file.isFile() && file.getName().endsWith(".class")) {
String className = packageName + "." + file.getName().replace(".class", "");
Class<?> klass = Class.forName(className);
dealClass(klass);
}
}
}
public void packageScan(String packageName) throws Exception {
String path = packageName.replace('.', '/');
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> urls = classLoader.getResources(path);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url.getProtocol().equals("file")) {
File file = new File(url.toURI());
scanFile(file, packageName);
} else if (url.getProtocol().equals("jar")) {
scanJar(url);
}
}
}
}
TypeParser.java
public class TypeParser {
private static final Map<String, Class<?>> classPool = new HashMap<String, Class<?>>();
private static final Map<String, IValueParser> valuePool = new HashMap<String, IValueParser>();
static {
classPool.put("byte", byte.class);
classPool.put("char", char.class);
classPool.put("boolean", boolean.class);
classPool.put("short", short.class);
classPool.put("int", int.class);
classPool.put("long", long.class);
classPool.put("float", float.class);
classPool.put("double", double.class);
classPool.put("string", String.class);
valuePool.put("byte", new IValueParser() {
@Override
public Object toValue(String str) {
return Byte.valueOf(str);
}
});
valuePool.put("char", new IValueParser() {
@Override
public Object toValue(String str) {
return str.charAt(0);
}
});
valuePool.put("boolean", new IValueParser() {
@Override
public Object toValue(String str) {
return Boolean.valueOf(str);
}
});
valuePool.put("short", new IValueParser() {
@Override
public Object toValue(String str) {
return Short.valueOf(str);
}
});
valuePool.put("int", new IValueParser() {
@Override
public Object toValue(String str) {
return Integer.valueOf(str);
}
});
valuePool.put("long", new IValueParser() {
@Override
public Object toValue(String str) {
return Long.valueOf(str);
}
});
valuePool.put("float", new IValueParser() {
@Override
public Object toValue(String str) {
return Float.valueOf(str);
}
});
valuePool.put("double", new IValueParser() {
@Override
public Object toValue(String str) {
return Double.valueOf(str);
}
});
valuePool.put("string", new IValueParser() {
@Override
public Object toValue(String str) {
return str;
}
});
}
public TypeParser() {
}
public static Class<?> toType(String strType) {
Class<?> result = classPool.get(strType);
if (result == null) {
try {
result = Class.forName(strType);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return result;
}
public static Object getValue(String type, String strValue) {
IValueParser valueParser = valuePool.get(type);
if (valueParser != null) {
return valueParser.toValue(strValue);
}
return null;
}
}
2.基础类
Component.java
/**
* 包扫描的入口,表示这个类存在需要被注入的成员或者生成bean的方法
* @Author :漠殇
* @Data :Create in 17:22 2021/7/18
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
Autowired.java
/**
* 表示该成员需要被注入
* @Author :漠殇
* @Data :Create in 17:24 2021/7/18
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
String value() default "";
}
Bean.java
/**
* 表示这个方法会生成一个Bean
* @Author :漠殇
* @Data :Create in 17:25 2021/7/18
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Bean {
}
BeanDefinition.java
/**
* @Author :漠殇
* @Data :Create in 17:29 2021/7/18
*/
public class BeanDefinition {
private Class<?> klass;
private Object object;
private boolean inject;
public BeanDefinition() {
}
public Class<?> getKlass() {
return klass;
}
public BeanDefinition setKlass(Class<?> klass) {
this.klass = klass;
return this;
}
public Object getObject() {
return object;
}
public BeanDefinition setObject(Object object) {
this.object = object;
return this;
}
public boolean isInject() {
return inject;
}
public BeanDefinition setInject(boolean inject) {
this.inject = inject;
return this;
}
@Override
public String toString() {
return "BeanDefinition{" +
"klass=" + klass +
", object=" + object +
", inject=" + inject +
'}';
}
}
BeanMethodDefinition.java
/**
* 存放方法,方法执行的对象,和方法还缺少依赖参数的个数
* 依赖参数个数为0,说明可以直接执行
* @Author :漠殇
* @Data :Create in 17:30 2021/7/18
*/
public class BeanMethodDefinition {
private Class<?> klass;
private Object object;
private Method method;
private int relyCount;
public BeanMethodDefinition() {
}
public Class<?> getKlass() {
return klass;
}
public BeanMethodDefinition setKlass(Class<?> klass) {
this.klass = klass;
return this;
}
public Object getObject() {
return object;
}
public BeanMethodDefinition setObject(Object object) {
this.object = object;
return this;
}
public Method getMethod() {
return method;
}
public BeanMethodDefinition setMethod(Method method) {
this.method = method;
return this;
}
public int getRelyCount() {
return relyCount;
}
public BeanMethodDefinition setRelyCount(int relyCount) {
this.relyCount = relyCount;
return this;
}
@Override
public String toString() {
return "BeanMethodDefinition{" +
"klass=" + klass +
", object=" + object +
", method=" + method +
", relyCount=" + relyCount +
'}';
}
}
3.核心类
BeanFactory.java
/**
* 所有的bean存放的位置
* 完成对bean的扫描,获取和判断bean是否存在等功能
* @Author :漠殇
* @Data :Create in 17:33 2021/7/18
*/
public class BeanFactory {
private static final Map<String, BeanDefinition> beanPool;
static {
beanPool = new HashMap<>();
}
public BeanFactory() {
}
/**
* 通过包路径,完成对bean工厂的初始化.
* 添加了Component注解的一定是一个bean,先将其加入beanFactory,并且调整依赖关系
* 然后对这个bean的方法进行扫描,若发现@bean注解,处理有参和无参方法
* 扫描完成后,将所有的依赖满足的method执行之,将结果返回值的Definition放回到bean工厂
* @param packagePath
*/
public static void scanPackage(String packagePath) {
try {
new PackageScanner() {
@Override
public void dealClass(Class<?> klass) throws Exception {
if (klass.isInterface()
||klass.isAnnotation()
||klass.isArray()
||klass.isEnum()
||klass.isPrimitive()
||!klass.isAnnotationPresent(Component.class)) {
return;
}
Object object = klass.newInstance();
BeanDefinition bd = new BeanDefinition();
bd.setKlass(klass).setObject(object).setInject(false);
beanPool.put(klass.getName(), bd);
MethodDependOnClass.judgeMethodDependOnClass(klass); //判断依赖关系
Method[] methods = klass.getDeclaredMethods();
for (Method method: methods) {
if (!method.isAnnotationPresent(Bean.class)) {
continue;
}
doMethodArgJudge(method, bd); //处理无参和有参方法
}
}
}.packageScan(packagePath);
doBeanMethod();//执行所有的完成依赖关系的BeanMethodDefinition
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取bean
* @param klass
* @param <T>
* @return
*/
public static <T> T getBean(Class<?> klass) {
return getBean(klass.getName());
}
/**
* 获取bean
* 先才beanFactory中寻找,如果未找到,寻找这个类的实现类,
* 再没有的话,就是这个bean不存在,或者生成这个bean的方法有参数未满足
* @param klassName
* @param <T>
* @return
*/
public static <T> T getBean(String klassName){
BeanDefinition beanDefinition = beanPool.get(klassName);
if (beanDefinition == null) {
//处理接口的实现类
beanDefinition = getImplementBean(klassName);
//处理不满足依赖和不存在的问题
if (beanDefinition == null) {
BeanMethodDefinition beanMethodDefinition = BeanMethodDepends.getBeanMethodDefinitionByClassName(klassName);
if (beanMethodDefinition == null) {
return null;
}
String str = BeanMethodDepends.getDependRelationship(beanMethodDefinition);
try {
throw new BeanMissingDependentException(str);
} catch (BeanMissingDependentException e) {
e.printStackTrace();
}
}
}
if (beanDefinition == null) {
return null;
}
Object bean = beanDefinition.getObject();
try {
doInject(beanDefinition);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return (T) bean;
}
/**
* 完成bean的注入
* 通过扫描@Autowired注解
* 判断是否为八大基本类型和String,如果是:如果value.length>0,进行值转换,负责,从beanFactory中获取
* 如果是其他类型,存在成员是接口类型:
* 如果value.length>0,根据value的值从beanFactory中获取(自定义获取)
* 否则,直接从beanFactory中获取(随机获取)
* 这里支持参数可以为null,即bean的某个成员的值可以为null
* @param bean
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
private static void doInject(BeanDefinition bean) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
if (bean.isInject()) {
return;
}
bean.setInject(true);
Class<?> klass = bean.getKlass();
Object object = bean.getObject();
Field[] fields = klass.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(Autowired.class)) {
continue;
}
Autowired autowired = field.getAnnotation(Autowired.class);
String value = autowired.value();
Object property = null;
Class<?> filedType = field.getType();
String typeName = filedType.getName();
if (filedType.isPrimitive() || filedType.isAssignableFrom(String.class)) {
if (value.length() <= 0 ) {
property = getBean(typeName);
} else {
property = TypeParser.getValue(typeName, value);
}
} else {
if (value.length() <= 0) {
property = getBean(typeName);
} else {
property = getBean(value);
}
}
String filedName = field.getName();
String setStr = "set" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
Method method = klass.getDeclaredMethod(setStr, filedType);
method.invoke(object, property);
}
}
/**
* 这里的方法必须含有返回值
* 处理无参方法和有参方法:
* 无参方法直接执行,生成bean
* 有参方法则进行依赖判断 BeanMethodDepends.addBeanMethod(method, object);
* @param method
* @param beanDefinition
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
private static void doMethodArgJudge(Method method, BeanDefinition beanDefinition) throws InvocationTargetException, IllegalAccessException {
Object object = beanDefinition.getObject();
if (method.getParameterCount() <= 0) {
Object res = method.invoke(object, new Object[] {});
Class<?> klass = res.getClass();
BeanDefinition bd = new BeanDefinition().setKlass(klass)
.setObject(res).setInject(false);
beanPool.put(klass.getName(), bd);
MethodDependOnClass.judgeMethodDependOnClass(klass); //判断依赖关系
return;
} else {
BeanMethodDepends.addBeanMethod(method, object);
}
}
/**
* 将所有完成依赖的方法执行之,生成bean,放入beanFactory中
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
private static void doBeanMethod() throws InvocationTargetException, IllegalAccessException {
while (BeanMethodDepends.hasNext()) {
BeanMethodDefinition beanMethodDefinition = BeanMethodDepends.next();
Object object = beanMethodDefinition.getObject();
Method method = beanMethodDefinition.getMethod();
Parameter[] parameters = method.getParameters();
Object[] objects = new Object[method.getParameterCount()];
for (int i = 0; i < parameters.length; i++) {
Class<?> klass = parameters[i].getType();
objects[i] = getBean(klass.getName());
}
Object bean = method.invoke(object, objects);
Class<?> beanClass = bean.getClass();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setKlass(beanClass).setObject(bean).setInject(false);
beanPool.put(beanClass.getName(), beanDefinition);
MethodDependOnClass.judgeMethodDependOnClass(beanClass); //判断依赖关系
}
}
/**
* 获取接口的实现类
* @param klassName
* @return
*/
private static BeanDefinition getImplementBean(String klassName){
try {
Class<?> klass = Class.forName(klassName);
if (klass.isInterface()) {
for (BeanDefinition beanDefinition : beanPool.values()) {
Class<?> beanClass = beanDefinition.getKlass();
if (klass.isAssignableFrom(beanClass)) {
return beanDefinition;
}
}
}
} catch (ClassNotFoundException e) {
return null;
}
return null;
}
/**
* 判断是否存在这个bean
* @param klassName
* @return
*/
public static boolean hasBean(String klassName) {
if (beanPool.containsKey(klassName)) {
return true;
}
if (getImplementBean(klassName) != null) {
return true;
}
return false;
}
/**
* 判断是否存在这个Bean
* @param klass
* @return
*/
public boolean hasBean(Class<?> klass) {
String klassName = klass.getName();
return hasBean(klassName);
}
}
BeanMethodDepends.java
/**
* 未满足依赖的methodDependPool和已经完成依赖的readyList
* 每当存入新的bean,这两个就会动态调整
* @Author :漠殇
* @Data :Create in 18:32 2021/7/18
*/
public class BeanMethodDepends {
private static final Map<BeanMethodDefinition, HashSet<Class<?>>> methodDependPool;
private static final List<BeanMethodDefinition> readyList;
static {
methodDependPool = new HashMap<>();
readyList = new ArrayList<>();
}
BeanMethodDepends() {
}
/**
* 当一个bean已生成,去调整之前需要依赖这个bean但之前没有满足的beanMethodDefinition
* 且调整后,如果beanMethodDefinition的未依赖参数个数为0,
* 则将其加入到readyList,并从methodDependPool中移除
* @param klass
* @param beanMethodDefinition
*/
static void adjustDependRelationship(Class<?> klass, BeanMethodDefinition beanMethodDefinition) {
HashSet<Class<?>> hashSet = methodDependPool.get(beanMethodDefinition);
hashSet.remove(klass);
beanMethodDefinition.setRelyCount(beanMethodDefinition.getRelyCount() - 1);
if (beanMethodDefinition.getRelyCount() <= 0) {
methodDependPool.remove(beanMethodDefinition);
readyList.add(beanMethodDefinition);
}
}
/**
* 判断readyList中是否还有元素
* @return
*/
static boolean hasNext() {
return !readyList.isEmpty();
}
/**
* 得到当前readyList中的第一个元素
* @return
*/
static BeanMethodDefinition next() {
if(!hasNext()) {
return null;
}
return readyList.remove(0);
}
/**
* 根据method和object构建BeanMethodDefinition
* 判断参数是否完成依赖,选择放入两个池子中的一个
* @param method
* @param object
*/
static void addBeanMethod(Method method, Object object) {
BeanMethodDefinition bmd = new BeanMethodDefinition();
bmd.setMethod(method).setObject(object).setKlass(method.getReturnType());
Parameter[] parameters = method.getParameters();
HashSet<Class<?>> hashSet = new HashSet<>();
for (Parameter parameter : parameters) {
Class<?> paraType = parameter.getType();
if (BeanFactory.hasBean(paraType.getName())) {
continue;
}
hashSet.add(paraType);
// 添加类和BeanMethodDefinition的依赖
MethodDependOnClass.addMethodDependOnClass(paraType, bmd);
}
int relyCount = hashSet.size();
bmd.setRelyCount(relyCount);
if (relyCount <= 0) {
readyList.add(bmd);
} else {
methodDependPool.put(bmd, hashSet);
}
}
/**
* 通过类名称,从methodDependPool中获取他对应的BeanMethodDefinition
* @param className
* @return
*/
static BeanMethodDefinition getBeanMethodDefinitionByClassName(String className) {
if (methodDependPool.isEmpty()) {
return null;
}
for (BeanMethodDefinition beanMethodDefinition : methodDependPool.keySet()) {
Class<?> klass = beanMethodDefinition.getKlass();
if (klass.getName().equals(className)) {
return beanMethodDefinition;
}
}
return null;
}
/**
* 构建beanMethodDefinition所未完成依赖参数的字符串
* @param beanMethodDefinition
* @return
*/
static String getDependRelationship(BeanMethodDefinition beanMethodDefinition) {
HashSet<Class<?>> hashSet = methodDependPool.get(beanMethodDefinition);
StringBuffer dependRelationship = new StringBuffer(beanMethodDefinition.getMethod().getName()
+ "依赖于 --> ");
boolean isFirst = true;
for (Iterator<Class<?>> it = hashSet.iterator(); it.hasNext(); ) {
Class<?> iterator = it.next();
if (isFirst) {
dependRelationship.append(iterator.getName()).append(" ");
isFirst = false;
} else {
dependRelationship.append(", ").append(iterator.getName()).append(" ");
}
}
return dependRelationship.toString();
}
}
MethodDependOnClass.java
/**
* 一个类可能存在多个BeanMethodDefinition去依赖他
* 当一个类进入到beanFactory中,可以将整个所依赖于他的BeanMethodDefinition的依赖关系全部进行调整
* @Author :漠殇
* @Data :Create in 15:09 2021/7/19
*/
public class MethodDependOnClass {
private static final Map<Class<?>, List<BeanMethodDefinition>> methodDependOnClassPool;
static {
methodDependOnClassPool = new HashMap<>();
}
MethodDependOnClass() {
}
/**
* 根据beanClass得到依赖于他的List<BeanMethodDefinition>
* @param beanClass
* @return
*/
static List<BeanMethodDefinition> getDependListByClass(Class<?> beanClass) {
return methodDependOnClassPool.get(beanClass);
}
/**
* 添加类与beanMethodDefinition的依赖列表
* @param beanClass
* @param beanMethodDefinition
*/
static void addMethodDependOnClass(Class<?> beanClass, BeanMethodDefinition beanMethodDefinition) {
if (!methodDependOnClassPool.containsKey(beanClass)) {
methodDependOnClassPool.put(beanClass, new ArrayList<>());
}
List<BeanMethodDefinition> beanMethodDefinitionList = methodDependOnClassPool.get(beanClass);
beanMethodDefinitionList.add(beanMethodDefinition);
}
/**
* 根据新生成的beanClass调整依赖关系
* @param beanClass
*/
static void judgeMethodDependOnClass(Class<?> beanClass) {
if (!methodDependOnClassPool.containsKey(beanClass)) {
return;
}
List<BeanMethodDefinition> beanMethodDefinitionList = methodDependOnClassPool.get(beanClass);
methodDependOnClassPool.remove(beanClass);
while (!beanMethodDefinitionList.isEmpty()) {
BeanMethodDefinition beanMethodDefinition = beanMethodDefinitionList.remove(0);
BeanMethodDepends.adjustDependRelationship(beanClass, beanMethodDefinition);
}
}
}
BeanMissingDependentException.java
/**
* 参数缺失错误
* @Author :漠殇
* @Data :Create in 18:47 2021/7/19
*/
public class BeanMissingDependentException extends Exception{
public BeanMissingDependentException() {
super();
}
public BeanMissingDependentException(String message) {
super(message);
}
public BeanMissingDependentException(String message, Throwable cause) {
super(message, cause);
}
public BeanMissingDependentException(Throwable cause) {
super(cause);
}
protected BeanMissingDependentException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
七,结语
笔者只进行了循环依赖问题、赋初值、Bean注解的测试、接口类对象的测试。测试结果很令人振奋。
大家如果进行测试,发现问题,请不吝赐教。