Spring---自动装配 autowire初探

  • 首先解释下什么是自动装配?

基于XML配置元数据,bean中可以使用<constructor-arg/>和<property/>属性来实现Spring的依赖注入

非自动装配时的spring文件配置如下:

<bean id="HelloWorld" class="test.spring.HelloWord">
    <property name="name" value="peter"></property>
    <property name="user">
        <ref bean="User"/>
    </property>
</bean>

类文件如下:

public class HelloWord {
    private User user;
    private String name;
}

自动装配,对于属性是对象引用的变量,可以采用注解的方式实现,代码如下

public class HelloWord {
	@Autowired
	private User user;
	private String name;
	
	public void setUser(User user) {
		this.user = user;
	}
}

经测试,setUser方法必需的,否则注入失败,为什么有的网友项目里没有该方法一样注入成功,今后再研究。

更新:spring配置文件中增加如下代码,可以不用setter方法

<context:annotation-config/>
或者
<context:component-scan base-package="test.spring"/>

即:在没有上述context配置项,需要setter方法,且在byType方式下,@Qualifier需要写在setter方法上面,写引用变量上会报错

Error creating bean with name 'distest' defined in class path resource [applicationcontext.xml]: Unsatisfied dependency expressed through bean property 'dislog': : No unique bean of type [test.spring.DiscountLogic] is defined: expected single matching bean but found 3: [lazydis, simdis, dislog]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [test.spring.DiscountLogic] is defined: expected single matching bean but found 3: [lazydis, simdis, dislog]
添加上述context配置项后,setter可要可不要,建议去掉,且在不写setter的byType模式下,即使matching bean大于一个能正常运行,经测试优先通过type匹配,如果匹配数大于1,在通过name匹配。


经过对比,其实自动装配只是减少了XML文件配置。把配置都注解到了JAVA代码里。spring3.2官方文档里对此有说法为

(Default) No autowiring. Bean references must be defined via a ref element.Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent,it documents the structure of a system.

我的理解,对于大型应用,还是建议使用非自动装配,这样可以更好的理解对象引用关系。

  • 什么是byName和byType?

spring3.2官方文档列出5种装配方式:no、byName、byType、constructor和autodetect。

byName,顾名思义就是通过bean的id或name查找类:

XML:
<bean id="dislog" class="test.spring.TimedDiscount"/>
<bean id="distest" class="test.spring.DiscountTest" autowire="byName"/>

JAVA:
public class DiscountTest {
    @Autowired
    private DiscountLogic dislog;
    public void setDislog(DiscountLogic dislog) {
        this.dislog = dislog;
    }
}

如上代码,spring容器就会去配置文件找name或者id为dislog的bean。

byTpye,顾名思义就是通过bean的class属性或class的父类查找,如果多个bean是相同class或是具有同一父类,就要使用@Qualifier指定具体实现类,其实还是归到了byName查找:

XML: 如下前三个类都实现DiscountLogic接口
<bean id="lazydis" class="test.spring.LazyDiscount"/>
<bean id="simdis" class="test.spring.SimpleDiscount"/>
<bean id="timeddis" class="test.spring.TimedDiscount"/>
<bean id="distest" class="test.spring.DiscountTest" autowire="byType">

JAVA:
public class DiscountTest {
    @Autowired
    private DiscountLogic dislog;

    @Qualifier("simdis")
    public void setDislog(DiscountLogic dislog) {
        this.dislog = dislog;
    }
}

注意,一开始Qualifier注解放在@Autowired下面,运行总是报错,后移动现在位置,运行正常,具体原因后面研究

解决byType匹配多个类报错问题,还有种解决方法,利用Resource注解。Resource是JDK6后支持的方法,需要引入annotations-api包,且配置文件含有上述context配置项。

  • Autowire和resource区别

@Autowire 默认按照类型装配,默认情况下它要求依赖对象必须存在如果允许为null,可以设置它required属性为false,如果我们想使用按照名称装配,可 以结合@Qualifier注解一起使用;

@Resource默认按照名称装配,当找不到与名称匹配的bean才会按照类型装配,可以通过name属性指定,如果没有指定name属 性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找 依赖对象.

注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖的对象时候,会回退到按照类型装配,但一旦指定了name属性,就只能按照名称 装配了.



作者:wuxinliulei
链接:https://www.zhihu.com/question/39356740/answer/80926247
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



附配置代码,粗体字为关键项目

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    	http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util-4.0.xsd
		http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.0.xsd"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p">
<bean id="lazydis" class="test.spring.LazyDiscount"></bean>
	<bean id="simdis" class="test.spring.SimpleDiscount">
		<property name="discountrate" value="80"></property>
	</bean>
	<bean id="dislog" class="test.spring.TimedDiscount"></bean>	
	<bean id="distest" class="test.spring.DiscountTest" autowire="byType">
	</bean>
    
    <context:annotation-config/>
    <context:component-scan base-package="test.spring"/>





        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值