spring依赖注入常用方式

978 阅读5分钟

在决定采用DI设计后,马上要考虑的是注入方式问题。DI中注入方式主要有构造函数注入和Setter注入(还有接口注入较少使用,本文不讨论)。这里我们还是通过具体例子来体会二者的区别:“人与身份证的依赖关系”适合采用Setter注入,因为人不是一出生就有身份证,而是到了法定年龄才有,用构造函数注入表达的语义与此相违背。相反“人与父母的依赖关系”则适合采用构造函数注入,因为亲子关系是从人一出生就建立的,用Setter注入必然使得对象创建后有一段时间处于非法状态,按契约式设计的术语即破坏了对象的不变量(invariant)。

可见,选择的关键还是对象生命周期问题。对象生命周期本身是现实世界的重要概念,因此,它在对现实世界建模见长的OO设计中当然也非常重要。不同OO语言间对象生命周期管理也有很大差别,主流OO语言中以C++最为复杂,C#次之,Java最单纯。但不管是复杂的C++还是单纯的Java我们都需要认真分析和考虑对象生命周期管理,实现合理的设计。

一、setting注入方式

这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是ioc的注入入口):

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(); 
} 
}

随后编写spring的xml文件,中的name属性是class属性的一个别名,class属性指类的全名,因为在SpringAction中有一个公共属性Springdao,所以要在标签中创建一个标签指定SpringDao。标签中的name就是SpringAction类中的SpringDao属性名,ref指下面<bean name="springDao"...>,这样其实是spring将SpringDaoImpl对象实例化并且调用SpringAction的setSpringDao方法将SpringDao注入:

<!--配置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>

二、构造器初始化注入

这种方式的注入是指带有参数的构造函数注入,看下面的例子,我创建了两个成员变量SpringDao和User,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在SpringAction的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDao和User两个参数值传进来:

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); 
} 
}

在XML文件中同样不用的形式,而是使用标签,ref属性同样指向其它标签的name属性:

<!--配置bean,配置后该类由spring管理--> 
<bean name="springAction" class="com.bless.springdemo.action.SpringAction"> 
<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置--> 
<constructor-arg ref="springDao"></constructor-arg> 
<constructor-arg 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 name="springAction" class="com.bless.springdemo.action.SpringAction"> 
<constructor-arg index="0" ref="springDao"></constructor-arg> 
<constructor-arg index="1" ref="user"></constructor-arg> 
</bean> 

另一种是设置参数类型:

<constructor-arg type="java.lang.String" ref=""/>

三、接口注入

原文链接:blog.csdn.net/bujidexinq/…

public class StupidStudent {
    public doHomewrok(SmartStudent smartStudent) {
        smartStudent.doHomework();
        System.out.println("学渣抄作业");
    }
}
public class StudentTest {
    public static void main(String[] args) {
        SmartStudent smartStudent = new SmartStudent();
        StupidStudent stupidStudent = new StupidStudent();
        stupidStudent.doHomework(smartStudent);
    }
}

采用这种注入方式,学渣只是在做作业时,才临时抱佛脚地找一下学霸

四、空间命名注入

<?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:p="http://www.springframework.org/schema/p"
       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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
">
 <!--命名空间P注入-->
    <bean id="car2" class="cn.happy.entity.Car">
        <property name="cname" value="毛驴"></property>
    </bean>
    <bean id="stu2" class="cn.happy.entity.Student" p:sname="李四" p:sage="18" p:car-ref="car2"></bean>
  //命名空间注入
    @Test
    public void myTest2(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        Student stu1=(Student) ac.getBean("stu1");
        Student stu2=(Student) ac.getBean("stu2");
        System.out.println("构造:"+stu1+"\n命名空间:"+stu2);

    }

五、注解注入

package cn.happy.entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

/**
 * Created by CKW on 2017/3/22.
 */
@Component("car") //不分层
/*@Repository  //dao层*/
/*@Service  //biz层*/
/*@Controller  //action层*/
public class Car {
    @Value("特斯拉")
    private String cname;
    
    @Override
    public String toString() {
        return getCname();
    }

    public Car() {
    }

    public Car(String cname) {
        this.cname = cname;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }
}
package cn.happy.entity;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * Created by CKW on 2017/3/22.
 */
@Component("student")
public class Student {
    @Value("撒打发")
    private String sname;
    @Value("20")
    private Integer sage;
    //jdk注解
    @Autowired
    @Qualifier("car")
    private Car car;

    @Override
    public String toString() {
        return "name="+getSname()+",age="+getSage()+",car="+getCar();
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    public Student() {

    }
    public String getSname() {
        return sname;
    }
    public Student(String sname, Integer sage, Car car) {
        this.sname = sname;
        this.sage = sage;
        this.car = car;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public Integer getSage() {
        return sage;
    }
    pblic void setSage(Integer sage) {
        this.sage = sage;
    }
}
<?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:p="http://www.springframework.org/schema/p"
       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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
">
<!--注解-->
    <!--配置包扫描器-->
    <context:component-scan base-package="cn.happy.entity"></context:component-scan>
//注解
@Test
public void myTest4(){
    ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
    Student stu=(Student)ac.getBean("student");
    System.out.println(stu.getCar().getCname());
}