【Spring源码系列】Bean生命周期-依赖注入

前言

一、依赖注入介绍

【自动注入】示例以及源码调试

代码示例:

@Component
public class OrderService {

}
public class UserService {

	private OrderService orderServiceWithUser;

	public void test(){
		System.out.println(orderServiceWithUser);
	}

    public void setOrderService(OrderService orderService) {
		this.orderServiceWithUser = orderService;
	}
@ComponentScan("com.cms")
public class AppConfig {

	@Bean(autowire = Autowire.BY_NAME)
	public UserService userService () {
		return new UserService();
	}
}
public class Test {

	public static void main(String[] args) {

		// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();
	}
}

源码:

	/* '自动注入'核心代码 。
		   		自动注入只有两种形式:@Bean(autowire = Autowire.BY_NAME)、@Bean(autowire = Autowire.BY_TYPE);
		   		如果只有@Bean,则是NO模型,下面的代码不会走。
		*
		* */
		// 下面这段代码没有进行属性赋值,而是往pvs里面添加东西
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			// MutablePropertyValues是PropertyValues具体的实现类
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set<String> result = new TreeSet<>();
		PropertyValues pvs = mbd.getPropertyValues();
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();

		// 什么样的属性能进行自动注入?
		// 1.该属性有对应的set方法(只对set方法进行依赖注入)
		// 2.没有在ignoredDependencyTypes中
		// 3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
		// 4.属性类型不是简单类型,比如int、Integer、int[]
		for (PropertyDescriptor pd : pds) {
			if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
					// 属性如果是简单类型则不会依赖注入。
					!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
				result.add(pd.getName());
			}
		}
		return StringUtils.toStringArray(result);
	}

自动注入流程:
1、我们演示通过自动注入-byName的方式进行 属性依赖注入;这个name指的是UserService中set方法后面的名称,也就是setOrderService方法set后面的orderService;
2、通过@Bean(autowire = Autowire.BY_NAME/BY_TYPE)的自动注入方式在真正进行属性依赖注入前,会调用unsatisfiedNonSimpleProperties方法进行过滤(如果是简单类型,则不会注入。但是如果是通过@Autowired注解的方式却是可以的,因为它底层没有对简单类型进行过滤);
2、无论是byName还是byType都会用到setOrderService(OrderService orderService)。如果是byName则spring到IOC容器中找name=orderService的bean(setOrderService方法中set后面的字符串名字),如果是byType则spring到IOC容器中找type=OrderService.class(setOrderService方法的参数)。如果找到则把OrderService对象赋值给setOrderService(OrderService orderService)方法的属性参数orderService;我们上面定义的setOrderService方法是把OrderService对象赋值给UserService中的orderServiceWithUser属性。

源码调试:
在这里插入图片描述1、我们演示的是**自动注入-byName方式**示例;
2、类中的每一个以set、get开头的方法都会封装成一个PropertyDescriptor对象。PropertyDescriptor对象是把类中以set、get开头的方法作为一个’属性描述对象‘;比如UserService中set方法会被PropertyDescriptor中的writeMethod记录;UserService的get方法会被PropertyDescriptor中的readMethod记录。
3、每个类默认都有getClass()方法
如上图中pds中存储两个元素(代表UserService中存在两个’属性‘):一个是name=class(readMethod),一个是name=orderService(writeMethod)。你可能奇怪,UserService中明明只有一个setOrderService方法,为什么还会出现getClass方法呢?因为每个类都有一个默认存在的方法:this.getClass()。
4、通过@Bean(autowire = Autowire.BY_NAME/BY_TYPE)的自动注入的方式不会把简单类型进行依赖注入。但是如果是通过@Autowired注解的方式却是可以的,因为它底层没有对简单类型进行过滤。简单类型如下:

	public static boolean isSimpleProperty(Class<?> type) {
		Assert.notNull(type, "'type' must not be null");
		// 简单类型 || 存储简单类型的数组
		return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
	}
	-------------------
	public static boolean isSimpleValueType(Class<?> type) {
		return (Void.class != type && void.class != type &&
				(ClassUtils.isPrimitiveOrWrapper(type) ||
				Enum.class.isAssignableFrom(type) ||
				CharSequence.class.isAssignableFrom(type) ||
				Number.class.isAssignableFrom(type) ||
				Date.class.isAssignableFrom(type) ||
				Temporal.class.isAssignableFrom(type) ||
				URI.class == type ||
				URL.class == type ||
				Locale.class == type ||
				Class.class == type));
	}

简单类型注入示例

autowire自动注入-简单类型属性注入示例:

@ComponentScan("com.cms")
public class AppConfig {

	@Bean
	public Number number () {
		return 1;
	}

	@Bean(autowire = Autowire.BY_NAME)
	public UserService userService () {
		return new UserService();
	}
}
public class UserService {

	private Number orderServiceWithUser;

	public void test(){
		System.out.println(orderServiceWithUser);
	}

    public void setOrderService(Number orderService) {
		this.orderServiceWithUser = orderService;
	}
}

运行test方法之后,结果为:null。
在这里插入图片描述

@Autowired手动注入-简单类型属性注入示例:

@ComponentScan("com.cms")
public class AppConfig {

	@Bean
	public Number number () {
		return 1;
	}

	@Bean(autowire = Autowire.BY_NAME)
	public UserService userService () {
		return new UserService();
	}
}
public class UserService {

	private Number orderServiceWithUser;

	public void test(){
		System.out.println(orderServiceWithUser);
	}

    public void setOrderService(Number orderService) {
		this.orderServiceWithUser = orderService;
	}
}

运行test方法之后,结果为:1。

二、依赖注入源码分析

声明关键点

源代码解读

源码位置:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@来杯咖啡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值