(Spring)IoC循环依赖、jar包类的处理
作者:互联网
在上次完成的IoC中,使用的BeanDefinition中有一个值用于判断是否注入完成,当我们遇到循环依赖时,代码会持续循环执行,原因是处理不到该判断值变化的部分,那么当我们把值变换提前,开始注入就进行更改,那么循环依赖就处理好了。
private static void doInject(BeanDefinition bean) throws Exception {
if (bean.isInject()) {
return;
}
bean.setInject(true);
Object object = bean.getObject();
Class<?> klass = bean.getKlass();
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<?> fieldType = field.getType();
String typeName = fieldType.getName();
if (value.length() <= 0) {
property = getBean(typeName);
} else {
String valueString = autowired.value();
property = TypeParser.getValue(typeName, valueString);
}
String fieldName = field.getName();
String setterName = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
Method setterMethod = klass.getDeclaredMethod(setterName,
new Class<?>[] {fieldType});
setterMethod.invoke(object, property);
}
}
对于Jar包内的类,采取由用户书写一个函数来实例化,但是由IoC调用的方法。即在本身包中新建一个类用于配置,其中书写的方法由新增的Bean注解标记,扫描到该方法,由IoC调用,即可将Jar包内的类实例出来。
对该方法应该如下理解:
1.方法的返回值是一个BeanDefinition,方便与放入pool
2.在方法中实例化相关类,这是主要目的
3.允许方法的参数是其他Bean,这点是处理难点,当所需的Bean未生成甚至该类在其他包内需要额外处理
此时重点问题是依赖存在于参数,那么如何判断依赖是否满足及当满足时运行该方法。
这种主要的应用场景是需要的Bean存在于其他Jar包内,无法获取该参数,即依赖此时无法完成,应利用Map先存储。
额外新建一个定义类BeanMethod,用于被Bean标记得方法,对应类的实例化对象,需要注入数目(即参数类型个数)
总共生成两个Map,一个List
第一个Map:用于存储方法BeanMethod和该类所需参数类型(使用Map存储,虽然值没有用处,但是借助Map键只能出现一次的特性可以解决参数重复出现的情况)的对应关系。
private static final Map<BeanMethodDefinition, Map<Class<?>, Integer>> beanMethodDepandent;
List:用于存储依赖关系以满足(即BeanMethod中的注入数目为0)的方法
private static final List<BeanMethodDefinition> allreadyBeanMethodPool;
第二个Map:该Map主要是为了效率考虑,我们每生成一个Bean,会生成其自己所需的依赖关系,那么依赖于这个Bean的方法,我们应该进行相应的处理,利用存储了该Bean及依赖于该Bean的BeanMethodDefinition列表,可以简化寻找的过程,按键找到对应的值,进行注入数目减一
private static final Map<Class<?>, List<BeanMethodDefinition>> beanClassPool;
jar包内的循环依赖是无解的,因为循环依赖的存在(即相关方法的参数发生了循环关系),所设置的方法参数不全,无法调用,即无法实例化出对象。此时解决方法是抛出一个异常,判断条件是该bean方法不为空(此点的因素是方法执行过后生成的带对象bean,会将方法设置为null)
标签:Map,依赖,包内,Spring,jar,bean,Bean,包类,方法 来源: https://blog.csdn.net/MagicSound/article/details/115606177