Spring学习笔记1—依赖注入(构造器注入、set注入和注解注入)

什么是依赖注入

在之前的java开发中,某个类中须要依赖其它类的方法时,一般是new一个依赖类再调用类实例的方法,这种方法耦合度过高而且不容易测试,spring提出了依赖注入的思想,即依赖类不禁程序员实例化,而是经过spring容器帮咱们new指定实例而且将实例注入到须要该对象的类中java

 

依赖注入的方式

依赖注入有3种方式:构造器注入、set注入和注解注入。程序员

1.构造器注入

构造器注入保证一些必要的属性在Bean实例化时就获得设置,而且确保了Bean实例在实例化后就可使用。spring

使用方式:less

  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:this

有时须要联合使用type和index才能肯定匹配项和构造函数入参的对应关系,看下面的代码。spa

public Car(String brand, String corp,double price){
    this.brand=brand;
    this.corp=corp;
    this.price=price;
}

public Car(String brand, String corp,int maxSpeed){
    this.brand=brand;
    this.corp=corp;
    this.maxSpeed=maxSpeed;
}

 这里,Car拥有两个重载的构造函数,它们都有三个入参。针对这种状况,按照入参索引的配置方式又难以知足要求了,这时须要联合使用<constructor-arg>的type和index才能解决问题.net

<!-- 构造函数注入(经过入参类型和位置索引肯定对应关系) -->
<!-- 对应public Car(String brand, String corp,int maxSpeed)构造函数 -->
<bean id="car3" class="com.spring.model.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,而被选择的构造函数可能并非用户所但愿的。所以,必须特别谨慎,以免潜在的错误。code

 

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 = user.getSchool();
}

这段代码执行会报错,由于Java类会先执行构造方法,而后再给注解了@Autowired 的user注入值,因此在执行构造方法的时候,就会报错。

解决办法是,使用构造器注入,以下:

private User user;
private String school;

@Autowired
public UserAccountServiceImpl(User user){
    this.user = user;
    this.school = user.getSchool();
}

 

 

参考:

@Autowired和构造方法执行的顺序解析

相关文章
相关标签/搜索