【Spring】2.0手写spring-DI

2.0手写spring-DI

依赖注入

依赖注入的分析

image

构造参数依赖定义分析

image

BeanReference说明

image

在BeanDefinition中增加获得构造参数的接口

image

从BeanDefinition中获得真实的值

从方法中添加了新的方法用于,从BeanDefinition中获得真实的值

image

确定构造方法或者工厂方法

image

对于原型Bean工厂需要每一次判断工厂方法,所以可以缓存在BeanDefinition中用于后续使用中

image

从BeanDefinition的参数选择当前的构造方法和工厂方法

            private Constructor<?> determineConstructor(BeanDefinition bd, Object[] args) throws Exception {
		Constructor<?> ct = null;
		if (args == null) {
			return bd.getBeanClass().getConstructor(null);
		}
		// 对于原型bean,从第二次开始获取bean实例时,可直接获得第一次缓存的构造方法。
		ct = bd.getConstructor();
		if (ct != null) {
			return ct;
		}
		// 1.根据参数类型获取精确匹配的构造方法
		Class<?>[] paramTypes = new Class[args.length];
		int j = 0;
		for (Object p : args) {
			paramTypes[j++] = p.getClass();
		}
		try {
			ct = bd.getBeanClass().getConstructor(paramTypes);
		} catch (Exception e) {
			// 这个异常不需要处理
		}
		if (ct == null) {
			// 2. 没有精确参数类型匹配的,则遍历匹配所有的构造方法
			// 判断逻辑:先判断参数数量,再依次比对形参类型与实参类型
			outer: for (Constructor<?> ct0 : bd.getBeanClass().getConstructors()) {
				Class<?>[] paramterTypes = ct0.getParameterTypes();
				if (paramterTypes.length == args.length) {
					for (int i = 0; i < paramterTypes.length; i++) {
						if (!paramterTypes[i].isAssignableFrom(args[i].getClass())) {
							continue outer;
						}
					}
					ct = ct0;
					break outer;
				}
			}
		}
		if (ct != null) {
			// 对于原型bean,可以缓存找到的构造方法,方便下次构造实例对象。在BeanDefinfition中获取设置所用构造方法的方法。
			// 同时在上面增加从beanDefinition中获取的逻辑。
			if (bd.isPrototype()) {
				bd.setConstructor(ct);
			}
			return ct;
		} else {
			throw new Exception("不存在对应的构造方法!" + bd);
		}
	}

从BeanDefinition的参数选择当前的工厂方法

private Method determineFactoryMethod(BeanDefinition bd, Object[] args, Class<?> type) throws Exception {
	if (type == null) {
		type = bd.getBeanClass();
	}
	String methodName = bd.getFactoryMethodName();

	if (args == null) {
		return type.getMethod(methodName, null);
	}
	Method m = null;
	// 对于原型bean,从第二次开始获取bean实例时,可直接获得第一次缓存的构造方法。
	m = bd.getFactoryMethod();
	if (m != null) {
		return m;
	}
	// 根据参数类型获取精确匹配的方法
	Class[] paramTypes = new Class[args.length];
	int j = 0;
	for (Object p : args) {
		paramTypes[j++] = p.getClass();
	}
	try {
		m = type.getMethod(methodName, paramTypes);
	} catch (Exception e) {
		// 这个异常不需要处理
	}

	if (m == null) {
		// 没有精确参数类型匹配的,则遍历匹配所有的方法
		// 判断逻辑:先判断参数数量,再依次比对形参类型与实参类型
		outer: for (Method m0 : type.getMethods()) {
			if (!m0.getName().equals(methodName)) {
				continue;
			}
			Class<?>[] paramterTypes = m.getParameterTypes();
			if (paramterTypes.length == args.length) {
				for (int i = 0; i < paramterTypes.length; i++) {
					if (!paramterTypes[i].isAssignableFrom(args[i].getClass())) {
						continue outer;
					}
				}
				m = m0;
				break outer;
			}
		}
	}
	if (m != null) {
		// 对于原型bean,可以缓存找到的方法,方便下次构造实例对象。在BeanDefinfition中获取设置所用方法的方法。
		// 同时在上面增加从beanDefinition中获取的逻辑。
		if (bd.isPrototype()) {
			bd.setFactoryMethod(m);
		}
		return m;
	} else {
		throw new Exception("不存在对应的构造方法!" + bd);
	}
}

循环依赖的处理

image

属性依赖的分析

image

BeanDefinition中的属性依赖

image

在DefaultDeanFactory 中增加setProperty的方法

image

private void setPropertyDIValues(BeanDefinition bd, Object instance) throws Exception {
	if (CollectionUtils.isEmpty(bd.getPropertyValues())) {
		return;
	}
	for (PropertyValue pv : bd.getPropertyValues()) {
		if (StringUtils.isBlank(pv.getName())) {
			continue;
		}
		Class<?> clazz = instance.getClass();
		Field p = clazz.getDeclaredField(pv.getName());

		p.setAccessible(true);

		Object rv = pv.getValue();
		Object v = null;
		if (rv == null) {
			v = null;
		} else if (rv instanceof BeanReference) {
			v = this.doGetBean(((BeanReference) rv).getBeanName());
		} else if (rv instanceof Object[]) {
			// TODO 处理集合中的bean引用
		} else if (rv instanceof Collection) {
			// TODO 处理集合中的bean引用
		} else if (rv instanceof Properties) {
			// TODO 处理properties中的bean引用
		} else if (rv instanceof Map) {
			// TODO 处理Map中的bean引用
		} else {
			v = rv;
		}

		p.set(instance, v);

	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值