Spring之属性填充

Spring给属性的方式一般有三种

1、通过在属性的添加@Autowired注解

@Component
public class UserService {

	@Autowired
	private OrderService orderService;

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

	public OrderService getOrderService() {
		return this.orderService;
	}
}

1、Spring在属性填充的时候,用org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessPropertyValues将类中属性使用@Autowired注解的属性查找出来。
2、同时在查找完成之后就会立刻赋值。

2、通过@Bean(autowire= Autowire.BY_NAME)

@Component
public class UserService {

	private OrderService orderService;

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

	public OrderService getOrderService() {
		return this.orderService;
	}
}

public class OrderService {
}

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

	@Bean(autowire= Autowire.BY_NAME)
	public OrderService orderService() {
		return new OrderService();
	}
}

1、这种方式可以不需要在private OrderService orderService上添加属性;
2、但是必须得有setOrderService方法;
3、在定义OrderService这个Bean的时候需要使用@Bean(autowire= Autowire.BY_NAME);
4、@Bean(autowire= Autowire.BY_NAME)表示通过名字添加。
5、BY_NAME使用的是setOrderService方法的OrderService,将首字母小写,开始查找Bean或者创建Bean。
6、通过这种方式会过滤掉简单类型,比如Enum、CharSequence、八大基本类型等等,即使向单例池中注册了Bean,获取的值也会是null。

通过这种方法添加属性的源码

protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		// 获取属性字段的名称
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			// 判断是否有这个属性字段对应的Bean或者BeanDefinfition
			if (containsBean(propertyName)) {
				// 创建Bean或者从单例池中获取字段对应的Bean
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				// 绑定Bean与属性对应Bean的关系
				registerDependentBean(propertyName, beanName);
				if (logger.isTraceEnabled()) {
					logger.trace("Added autowiring by name from bean name '" + beanName +
							"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
							"' by name: no matching bean found");
				}
			}
		}
	}

这个方法主要是通过BY_NAME找出有多少个属性需要被填充值。

3、通过@Bean(autowire= Autowire.BY_TYPE)

@Component
public class UserService {

	private OrderService orderService;

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

	public OrderService getOrderService() {
		return this.orderService;
	}
}

public class OrderService {
}

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

	@Bean(autowire= Autowire.BY_TYPE)
	public OrderService orderService() {
		return new OrderService();
	}
}

1、这种方式可以不需要在private OrderService orderService上添加属性;
2、但是必须得有setOrderService方法;
3、在定义OrderService这个Bean的时候需要使用@Bean(autowire= Autowire.BY_TYPE);
4、@Bean(autowire= Autowire.BY_TYPE)表示通过名字添加。
5、BY_TYPE使用的是setOrderService方法的参数,通过将参数查找出来,创建Bean或者从单例池中把对象找出赋值。
6、通过这种方式会过滤掉简单类型,比如Enum、CharSequence、八大基本类型等等,即使向单例池中注册了Bean,获取的值也会是null。

通过这种方法添加属性的源码

protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		// 获取属性字段的名称
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			try {
				// 获取属性字段描述器
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				if (Object.class != pd.getPropertyType()) {
					// 获取set方法里的参数
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
					// 获得参数的描述器
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					// 获得参数的值
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
						pvs.add(propertyName, autowiredArgument);
					}
					for (String autowiredBeanName : autowiredBeanNames) {
						// 属性填充
						registerDependentBean(autowiredBeanName, beanName);
						if (logger.isTraceEnabled()) {
							logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
									propertyName + "' to bean named '" + autowiredBeanName + "'");
						}
					}
					autowiredBeanNames.clear();
				}
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
			}
		}
	}

4、三种赋值的对比。

1、在Spring源码中,第一种会在查找出来属性之后立刻赋值,第二种和第三种则是需要在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues这个方法中被复制。
2、假如实现了MergedBeanDefinitionPostProcessor接口,手动给这个属性赋值,最终orderService将会是用户自己设定的值。

@Component
public class SpringTestBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if (beanName.equals("userService")) {
			MutablePropertyValues propertyValues = new MutablePropertyValues();
			OrderService orderService = new OrderService();
			System.out.println("beanPostProcessor: "+orderService);
			propertyValues.addPropertyValue("orderService", orderService);
			beanDefinition.setPropertyValues(propertyValues);
		}
	}

	@Override
	public void resetBeanDefinition(String beanName) {
		MergedBeanDefinitionPostProcessor.super.resetBeanDefinition(beanName);
	}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
OrderService orderService = (OrderService) applicationContext.getBean("orderService");
System.out.println("UserService OrderService: "+userService.getOrderService());
System.out.println("OrderService: "+orderService);

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/6439.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

b站第一,Python自动化测试实战详细教学,3天教你学会自动化测试

目录 简介 Python自动化测试概述 Python自动化测试目标 Python自动化测试流程 1. 测试计划和设计 2. 测试脚本开发 3. 测试执行和管理 4. 测试维护和优化 Python自动化测试最佳实践 Python自动化测试工具和框架 结论 简介 自动化测试是软件开发过程中一个必不可少的…

【Django 网页Web开发】22. 实战项目:简单的文件上传(15)(保姆级图文)

目录实现效果1. url.py2. upload_list.html3. upload.py总结欢迎关注 『Django 网页Web开发』 系列&#xff0c;持续更新中 欢迎关注 『Django 网页Web开发』 系列&#xff0c;持续更新中 实现效果 1. url.py path(upload/list/, upload.upload_list),2. upload_list.html {% e…

Python中进程和线程到底有什么区别?

人生苦短&#xff0c;我用python python 安装包资料:点击此处跳转文末名片获取 一、进程和线程的关系 线程与进程的区别可以归纳为以下4点&#xff1a; 地址空间和其它资源&#xff08;如打开文件&#xff09;&#xff1a;进程间相互独立&#xff0c;同一进程的各线程间共享。…

操作系统(2.6)--进程通信

进程通信是指进程之间的信息交换。 在进程之间要传送大量数据时&#xff0c;应当利用OS提供的高级通信工具&#xff0c;该工具最主要的特点是: (1)使用方便。OS隐藏了实现进程通信的具体细节&#xff0c;向用户提供了一组用于实现高级通信的命令(原语)&#xff0c;用户可方便地…

ThreeJS-太阳球围绕旋转(二十四)

数学小知识&#xff1a; 我们根据旋转角度θ可以计算出任意时刻的x,y sinθ y0/r; 因此y0 rsinθ, cosθ x0/r,因此x0 rcosθ, 小拓展&#xff1a; y0^ x0^ - r^2*sinθ^2 r^2*cosθ^2 r^2*(sinθ^2 cosθ^2) r^2; 这也是为什么在极坐标方程中 y0 rsinθ, x0 rcos…

15_I.MX6ULL_LCD显示原理

目录 LCD简介 分辨率 像素格式 LCD屏幕接口 LCD时间参数 RGB LCD屏幕时序 像素时钟 显存 LCD简介 LCD全称是Liquid Crystal Display,也就是液晶显示器,是现在最常用到的显示器,手机、电脑、各种人机交互设备等基本都用到了LCD,最常见就是手机和电脑显示器了。LCD的构造…

帮公司面试了一个32岁的程序员,只因这一个细节,被我一眼看穿是培训班出来的,没啥工作经验...

首先&#xff0c;我说一句&#xff1a;培训出来的&#xff0c;优秀学员大有人在&#xff0c;我不希望因为带着培训的标签而无法达到用人单位和候选人的双向匹配&#xff0c;是非常遗憾的事情。 最近&#xff0c;在网上看到这样一个留言&#xff0c;引发了程序员这个圈子不少的…

ChatGPT全球大封号!数10万企业停摆:第一批玩AI的人,被AI给玩了

观点| Mr.K 主笔| Wendy.L 编辑| Emma来源| 技术领导力(ID&#xff1a;jishulingdaoli)3月31日&#xff0c;Open AI就开始无征兆的进行全球大封号&#xff0c;其中亚洲是重灾区&#xff0c;官方没有给出任何声明&#xff0c;具体原因不得而知。并且暂停了这些地区新账号的注…

【从零开始学习 UVM】6.4、UVM 激励产生 —— uvm_do 宏详解

请注意,start方法的call_pre_post字段设置为0,这意味着在使用这些序列宏时,序列的pre_body和post_body方法将永远不会被调用。否则,执行流程与通过start方法执行序列时类似。 文章目录 执行序列宏介绍Example执行序列宏介绍 使用序列宏的优点是可以使用内联约束,但是您失…

实验一 跨VLAN访问

目录 一、按照拓扑图配置VLAN&#xff0c;并实现跨VLAN间的访问。 二、实验环境 三、实验步骤 一、按照拓扑图配置VLAN&#xff0c;并实现跨VLAN间的访问。 1、配置好交换机的VLAN和各个终端的地址&#xff0c;实现各个VLAN内能连通。 2、开启两个交换机的VTY连接&#xff0…

基于STM32F103——XGZP6847D压力传感器+串口打印

基于STM32F103—XGZP6847D压力传感器串口打印基本介绍概述产品特点引脚的连接 (IIC通信)名称含义的介绍I2C通信协议 (设备地址是 0x6D)寄存器描述工作模式寄存器Reg0x30&#xff08;测量命令寄存器&#xff09;Reg0xA5Reg0xA6模式说明组合数据采集模式休眠数据采集模式代码编写…

MyBatisPlus

今日目标基于MyBatisPlus完成标准Dao的增删改查功能掌握MyBatisPlus中的分页及条件查询构建掌握主键ID的生成策略了解MyBatisPlus的代码生成器1&#xff0c;MyBatisPlus入门案例与简介这一节我们来学习下MyBatisPlus的入门案例与简介&#xff0c;这个和其他课程都不太一样&…

[CF复盘] Codeforces Round 863 (Div. 3) 20230404

[TOC]([CF复盘] Codeforces Round 863 (Div. 3) 20230404 ) 一、本周周赛总结 做到E&#xff0c;但DE都TLE&#xff0c;很难受。 A 贪心。 B 坐标运算。 C 贪心构造。 D 分治DFS。 E 九进制模拟。 二、 A. Insert Digit 链接: A. Insert Digit 1. 题目描述 2. 思路分析…

skimage.filters.apply_hysteresis_threshold详解

本文内容均参考scipy1.9.1scipy1.9.1scipy1.9.1版本的源码&#xff0c;若有任何不当欢迎指出 我们截取官方注释如下&#xff1a; def apply_hysteresis_threshold(image, low, high):"""Apply hysteresis thresholding to image.This algorithm finds regions …

RabbitMQ中TTL

目录一、TTL1.控制后台演示消息过期2.代码实现2.1 队列统一过期2.2 消息过期一、TTL TTL 全称 Time To Live&#xff08;存活时间/过期时间&#xff09;。 当消息到达存活时间后&#xff0c;还没有被消费&#xff0c;会被自动清除。 RabbitMQ可以对消息设置过期时间&#xff0…

QT与Halcon联编应用开发-设置软件图标Icon

VS+Qt应用开发-设置软件图标 设置软件exe图标设置运行时标题栏和任务栏图标默认的Qt是没有图标的,如下图所示,可以在Qt应用程序发布时和应用程序运行时给应用程序加上图标。 任务栏图标: 软件左上角图标 可执行程序图标

原来count(*)是接口性能差的真凶

以下文章来源于苏三说技术 &#xff0c;作者苏三呀 一.前言 最近我在公司优化过几个慢查询接口的性能&#xff0c;总结了一些心得体会拿出来跟大家一起分享一下&#xff0c;希望对你会有所帮助。 我们使用的数据库是Mysql8&#xff0c;使用的存储引擎是Innodb。这次优化除了优…

通过Chrome打开IE浏览器并跳转到指定页面并传递参数

通过Chrome打开IE浏览器并跳转到指定页面并传递参数 方式一&#xff1a;通过浏览器打开ie浏览器&#xff08;可以换做其他应用&#xff09;&#xff0c;跳转到指定页面&#xff08;方式一只支持单个参数&#xff09; 1、新建alert.reg Windows Registry Editor Version 5.00…

IOC/DI的注解开发

IOC/DI注解开发3&#xff0c;IOC/DI注解开发3.1 环境准备3.2 注解开发定义bean步骤1:删除原XML配置步骤2:Dao上添加注解步骤3:配置Spring的注解包扫描步骤4&#xff1a;运行程序步骤5:Service上添加注解步骤6:运行程序知识点1:Component等3.2 纯注解开发模式3.2.1 思路分析3.2.…

https和ssl网关在各安全层面的应用场景及测评要点

1、https和https实现 SSL/TLS协议是独立的概念&#xff08;这里的重点是https和ssl v**&#xff0c;关于ssl/tls协议就不展开说了&#xff09;&#xff0c;可以实现对基于TCP/UDP应用的安全保护&#xff0c;如https和sftp等。 https是其中应用非常广泛的一种&#xff0c;即Hype…