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


    前言

    一、依赖注入介绍

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

    代码示例:

    @Component
    public class OrderService {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    public class UserService {
    
    	private OrderService orderServiceWithUser;
    
    	public void test(){
    		System.out.println(orderServiceWithUser);
    	}
    
        public void setOrderService(OrderService orderService) {
    		this.orderServiceWithUser = orderService;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    @ComponentScan("com.cms")
    public class AppConfig {
    
    	@Bean(autowire = Autowire.BY_NAME)
    	public UserService userService () {
    		return new UserService();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    public class Test {
    
    	public static void main(String[] args) {
    
    		// 创建一个Spring容器
    		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
    
    		UserService userService = (UserService) applicationContext.getBean("userService");
    		userService.test();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    源码:

    	/* '自动注入'核心代码 。
    		   		自动注入只有两种形式:@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;
    		}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    	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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    自动注入流程:
    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));
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    简单类型注入示例

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

    @ComponentScan("com.cms")
    public class AppConfig {
    
    	@Bean
    	public Number number () {
    		return 1;
    	}
    
    	@Bean(autowire = Autowire.BY_NAME)
    	public UserService userService () {
    		return new UserService();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class UserService {
    
    	private Number orderServiceWithUser;
    
    	public void test(){
    		System.out.println(orderServiceWithUser);
    	}
    
        public void setOrderService(Number orderService) {
    		this.orderServiceWithUser = orderService;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行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();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class UserService {
    
    	private Number orderServiceWithUser;
    
    	public void test(){
    		System.out.println(orderServiceWithUser);
    	}
    
        public void setOrderService(Number orderService) {
    		this.orderServiceWithUser = orderService;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    二、依赖注入源码分析

    声明关键点

    源代码解读

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

  • 相关阅读:
    十. Linux关机重启命令与Vim编辑的使用
    色彩的基础知识——适用于camera tuning
    div内文字水平居中+垂直居中
    Vue学习
    智能热水器丨打造智能家居新体验
    Python 潮流周刊#54:ChatTTS 强大的文本生成语音模型
    循环神经网络(RNN)之长短期记忆(LSTM)
    AvaSpec-ULS2048光谱仪测定地物高光谱曲线的方法
    VirtualBox安装CentOS 7教程
    flink实战--flinksql 窗口TVF
  • 原文地址:https://blog.csdn.net/qq_43783527/article/details/128169282