【转】Spring学习笔记1—依赖注⼊(构造器注⼊、set注⼊和注
解注⼊)
什么是依赖注⼊
在以前的java开发中,某个类中需要依赖其它类的⽅法时,通常是new⼀个依赖类再调⽤类实例的⽅法,这种⽅法耦合度太⾼并且不容易测试,spring提出了依赖注⼊的思想,即依赖类不由程序员实例化,⽽是通过spring容器帮我们new指定实例并且将实例注⼊到需要该对象的类中。
依赖注⼊的⽅式
依赖注⼊有3种⽅式:构造器注⼊、set注⼊和注解注⼊。
resource和autowired注解的区别1.构造器注⼊
构造器注⼊保证⼀些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使⽤。
使⽤⽅式:
1. 在类中,不⽤为属性设置setter⽅法,但是需要⽣成该类带参的构造⽅法。
2. 在配置⽂件中配置该类的bean,并配置构造器,在配置构造器中⽤到了<constructor-arg>节点,该节点有四个属性
index:指定注⼊属性的顺序索引,从0开始;
type:指该属性所对应的类型;
ref:引⽤的依赖对象;
value:当注⼊的不是依赖对象,⽽是基本数据类型时,就⽤value;
例⼦1:
public class SpringAction {
//注⼊对象springDao
private SpringDao springDao;
private User user;
public SpringAction(SpringDao springDao,User user){
this.springDao = springDao;
this.user = user;
System.out.println("构造⽅法调⽤springDao和user");
}
public void save(){
user.setName("卡卡");
springDao.save(user);
}
}
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(2)创建构造器注⼊,如果主类有带参的构造⽅法则需添加此配置-->
<constructor-arg index="0" ref="springDao"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
<bean name="user" class="com.bless.springdemo.vo.User"></bean>
其中index属性表⽰注⼊的bean在构造⽅法中的参数顺序。
例⼦2:
有时需要联合使⽤type和index才能确定匹配项和构造函数⼊参的对应关系,看下⾯的代码。
public Car(String brand, String corp,double price){
this.brand=brand;
this.price=price;
}
public Car(String brand, String corp,int maxSpeed){
this.brand=brand;
this.maxSpeed=maxSpeed;
}
这⾥,Car拥有两个重载的构造函数,它们都有三个⼊参。针对这种情况,按照⼊参索引的配置⽅式⼜难以满⾜要求了,这时需要联合使⽤<constructor-arg>的type和index才能解决问题
<!-- 构造函数注⼊(通过⼊参类型和位置索引确定对应关系) -->
<!-- 对应public Car(String brand, String corp,int maxSpeed)构造函数 -->
<bean id="car3" class="del.Car">
<constructor-arg index="0" type="java.lang.String" value="奔驰"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="中国⼀汽"></constructor-arg>
<constructor-arg index="2" type="int" value="200"></constructor-arg>
</bean>
对于由于参数数⽬相同⽽类型不同所引起的潜在配置歧义问题,Spring容器可以正确启动且不会给出报错信息,它将随机采⽤⼀个匹配的构造函数实例化Bean,⽽被选择的构造函数可能并不是⽤户所希望的。因此,必须特别谨慎,以避免潜在的错误。
2.set注⼊
set注⼊要求Bean提供⼀个默认的构造函数,并为需要注⼊的属性提供对应的Setter⽅法。
Spring先调⽤Bean的默认构造函数实例化Bean对象,然后通过反射的⽅式调⽤Setter⽅法注⼊属性值。
假设Bean显⽰定义了⼀个带参的构造函数,则需要同时提供⼀个默认⽆参的构造函数,否则使⽤属性注⼊时将抛出异常。
例⼦1:
package com.bless.springdemo.action;
public class SpringAction {
//注⼊对象springDao
private SpringDao springDao;
//⼀定要写被注⼊对象的set⽅法
public void setSpringDao(SpringDao springDao) {
this.springDao = springDao;
}
public void ok(){
springDao.ok();
}
}
<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(1)依赖注⼊,配置当前类中相应的属性-->
<property name="springDao" ref="springDao"></property>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
这⾥不再使⽤“constructor-arg”⽽是使⽤“property”属性。
3.注解注⼊
注解注⼊其实是使⽤注解的⽅式进⾏构造器注⼊或者set注⼊。
spring2.5开始提供了基于注解(Annotation-based)的配置,我们可以通过注解的⽅式来完成注⼊依赖。在Java代码中可以使⽤
@Resource或者@Autowired注解⽅式来经⾏注⼊。
虽然@Resource和@Autowired都可以来完成注⼊依赖,但它们之间是有区别的:
1. @Resource默认是按照名称来装配注⼊的,只有当不到与名称匹配的bean才会按照类型来装配注⼊;
2. @Autowired默认是按照类型装配注⼊的,如果想按照名称来转配注⼊,则需要结合@Qualifier⼀起使⽤;
3. @Resource注解是⼜J2EE提供,⽽@Autowired是由Spring提供;
例⼦:
package com.bless.springdemo.action;
public class SpringAction {
//注⼊对象springDao
@Resource
private SpringDao springDao;
//不需要要写被注⼊对象的set⽅法,spring会帮你get/set
public void ok(){
springDao.ok();
}
}
<context:annotation-config/>
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--不需要配置属性,@Resource默认按照名称装配注⼊-->
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
<context:annotation-config/>的作⽤是开启注解。
@Autowired的同理,只不过默认是按照类型装配注⼊。
补充:
@Autowired 可以对成员变量、⽅法以及构造函数进⾏注释。那么对成员变量和构造函数进⾏注释⼜有什么区别呢?
先来看下⾯⼀段代码:
@Autowired
private User user;
private String school;
public UserAccountServiceImpl(){
this.school = School();
}
这段代码执⾏会报错,因为Java类会先执⾏构造⽅法,然后再给注解了@Autowired 的user注⼊值,所以在执⾏构造⽅法的时候,就会报错。
解决办法是,使⽤构造器注⼊,如下:
private User user;
private String school;
@Autowired
public UserAccountServiceImpl(User user){
this.user = user;
this.school = School();
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论