模拟Spring框架(循环依赖,循环注入)—Bean注解处理带参方法(下篇)

上篇中已经对于Spring框架有关IOC和DI进行了说明,但是后续对于Bean注解处理方法只涉及到了对不带参数的方法的处理(具体操作可以在上篇文章
中详细回顾),那本篇就继续针对有Bean注解的带参数的方法处理来进一步介绍:

1)“循环依赖”关系的简单介绍

先给出一个简单例子,解释循环依赖的关系,分别给出三个类A,B,C,A类中有B类型的成员,B类中有C类型的成员,C类中有A类型的成员,并给出三个类的toString()方法,方便之后输出;

@Component
public class A {
   
	
	@AutoWired
	private B b;

	public B getB() {
   
		return b;
	}

	public void setB(B b) {
   
		this.b = b;
	}

	@Override
	public String toString() {
   
		return "A类中的b成员:[" + b + "]";
	}
}
@Component
public class B {
   

	@AutoWired
	private C c;
	
	public B() {
   
	}

	public C getC() {
   
		return c;
	}

	public void setC(C c) {
   
		this.c = c;
	}

	@Override
	public String toString() {
   
		return "B类中的c成员:[" + c + "]";
	}
}
@Component
public class C {
   

	@AutoWired
	private A a;
	
	public C() {
   
	}

	public A getA() {
   
		return a;
	}

	public void setA(A a) {
   
		this.a = a;
	}

	@Override
	public String toString() {
   
		return "C类中的a成员:" + (a == null ? "null" : "不为null");
	}
}

像上述代码所示,三个类之间相互之间都存在依赖关系,就是我们所说的简单的“循环依赖”。

2)Bean注解处理带参方法的思想介绍

接上篇中的内容来继续解释,我们定义了一个Map(BeanPool)用于存放被Component注解的类(即,相关之间有依赖关系的类),一些不能直接加入BeanPool的类通过利用Bean注解来解决,之前我对于Bean注解只把它用在无参方法上,现在需要继续探讨带参方法的处理,希望可以实现通过Bean注解实现无参和带参方法

解决带参方法问题的大体思想是:

对于某个带参的方法,根据BeanPool看参数满不满足,将不满足的参数加到一个Map(dependenceMethodPool )中,并将此时不能执行的方法放到一个不可执行列表uninvokeMethodList 中,随着扫描的进行,如果有参数满足了,就把参数从Map中删掉,将方法参数个数减1,当参数个数值减为0了,表示该方法可以执行了,再将该方法从不可执行列表uninvokeMethodList 移入到一个可执行列表invokeMethodList 中。

通过图示简单来看一下:
在这里插入图片描述

3)Bean注解处理带参方法的具体实现(循环注入)

当扫描到某个带有Bean注解的方法是,先判断该方法有没有带参数,若为无参方法,就按上篇讲到的处理无参方法的操作进行,若带参先通过方法得到所有参数,把参数类型当成键,值不重要,在这里当成0就可以,放入一个Map中

注意

之所以不把参数存方到List列表中,是因为每次将参数放入List,都需要检查一遍前面有没有放入过该参数,如此一来时间复杂度会很高,不推荐使用List方式存储。而用Map来存放的话,是通过键值对的方式,一个键只能对应一个值,当有相同的键加入时Map时,会自动覆盖前面这个键对应的值,不需要再花费时间复杂度去检查有没有,也不存在键的重复,这个过程中,键所对应的的值并不重要,因为我们需要的只是不重复的参数类型。就算某个方法的参数有三个,其中两个参数是同一个类型的,虽然我们把参数在Map中加入了三次,但是实际上Map中存放的只有两种参数类型,这样避免了对相同参数类型的参数重复加入。

遍历Map,根据Map中的参数类型查看该类型是否是BeanPool中的类,如果是的话就表示该类可以自动完成初始化,将这个类先临时存到一个列表中,依次操作,等到整个Map都遍历结束,再根据列表中存放的类将Map中相应的键值对删除,就得到了方法中不满足的参数类型的Map(有一点需要注意,List不能进行边遍历边删除的操作,因为列表没删除一个内容,整个列表中的位置会发生移动,如果边遍历边删除,最多也只能删除列表中的一半内容,在这里不进一步给出验证过程,大家有兴趣的可以自行验证)。具体的代码如下(给出的只是关键代码,不能直接复制运行):

private static Map<Class<?>, Integer> getParaMap(Method method) {
   
		Map<Class<?>, Integer> paraPool = new HashMap<Class<?>, Integer>();
		Class<?>[] paraTypes = method.getParameterTypes();
		
		for(int index = 0 ;index < paraTypes.length ; index++) {
   
			paraPool.put(paraTypes[index], 0);
		}
		
		List<Class<?>> tmpParaList = new ArrayList<Class<?>>();
		for(Class<?> beanClass : paraPool.keySet(
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值