Spring IOC、DI(Dependency injection)

一、Spring IOC、DI 解释

Spring Ioc容器(ApplicationContext)负责创建Bean,并通过容器将这些创建的Bean注入到需要他们的消费者Bean中。Spring提供使用Xml、注解java配置的方式创建和注入,容器解析这些配置信息进行Bean的初始化,配置和依赖管理。
DI(依赖注入),依赖即以组合形式定义其他类型的对象定义为本类的成员变量(对象初始化时依赖于成员变量的初始化),而依赖注入即初始化成员变量,spring依赖注入即为spring在构建对象时对对象的变量进行初始化,即当定义一个对象时,由spring控制对象的创建和初始化。

二、测试用例User.java和Grade.java

---Grade.java

package com.jty.testSpring;
public class Grade {
private String schoolName;//学校名
private String gradeName;//年级名

   public Grade() {
         super();
   }
   public Grade(String schoolName, String gradeName) {
         super();
         this.schoolName = schoolName;
         this.gradeName = gradeName;
   }
   public String getSchoolName() {
         return schoolName;
   }
   public void setSchoolName(String schoolName) {
         this.schoolName = schoolName;
   }
   public String getGradeName() {
         return gradeName;
   }
   public void setGradeName(String gradeName) {
         this.gradeName = gradeName;
   }
   @Override
   public String toString() {
         return "Grade [schoolName=" + schoolName + ", gradeName=" + gradeName + "]";
   }

}
---User.java

package com.jty.testSpring;
public class Student {
private String name;//姓名
private int ages;//年龄
private String address;//地址
private double cost;//零花钱
private Grade grade;

   public Student() {
         super();
         System.out.println("=========调用默认构造器============");
         this.name="默认构造器";
         this.ages=20;
         this.address="江苏省南京市";
         this.cost=20.00;
         this.grade=new Grade("第三中学","三年级");
   }
   public Student(String name, Integer ages, String address, Double cost, Grade grade) {
         super();
         System.out.println("=========调用带参构造器============");
         this.name = name;
         this.ages = ages;
         this.address = address;
         this.cost = cost;
         this.grade = grade;
   }
   public String getName() {
         return name;
   }
   public void setName(String name) {
         this.name = name;
   }
   public int getAges() {
         return ages;
   }
   public void setAges(int ages) {
         this.ages = ages;
   }
   public String getAddress() {
         return address;
   }
   public void setAddress(String address) {
         this.address = address;
   }
   public double getCost() {
         return cost;
   }
   public void setCost(double cost) {
         this.cost = cost;
   }
   public Grade getGrade() {
         return grade;
   }
   public void setGrade(Grade grade) {
         this.grade = grade;
   }
   @Override
   public String toString() {
         return "Student [name=" + name + ", ages=" + ages + ", address=" + address + ", cost=" + cost + ", grade="
                       + grade + "]";
   }

}

三、构造器注入

(1)默认构造器
注:提供默认构造器

---applicationContext.xml

<bean id="student1" class="com.jty.testSpring.Student">  
</bean>

---TestStudent.java

package com.jty.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent
{
public static void main(String []agrs) {
//获取ioc容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student1=applicationContext.getBean(Student.class,"student1");
System.out.println("生成学生用户:"+student1);
}
}
输出:
=调用默认构造器====
生成用户:Student [name=默认构造器, ages=20, address=江苏省南京市, cost=20.0, grade=Grade [schoolName=第三中学, gradeName=三年级]]
(2)显示使用构造器注入
注:必须提供带参构造器,type属性可省略,且只能使用包装类,可使用index-value或type-value属性代替name-value进行初始化,序号从0开始

---applicationContext.xml

---TestStudent.java

package com.jty.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent
{
public static void main(String []agrs) {
//获取ioc容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student2=applicationContext.getBean(Student.class,"student2");
System.out.println("生成学生用户:"+student2);
}
}
输出:
=调用带参构造器====
生成学生用户:Student [name=带参数构造器, ages=21, address=江苏省南京市, cost=20.0, grade=Grade [schoolName=第四中学, gradeName=二年级]]

四、Setter注入

注:必须编写setter方法
---applicationContext.xml

<bean id="grade" class="com.jty.testSpring.Grade">
   <constructor-arg name="schoolName" value="第四中学" type="java.lang.String"></constructor-arg>
   <constructor-arg name="gradeName" value="二年级" type="java.lang.String"></constructor-arg>
</bean>
<bean id="student3" class="com.jty.testSpring.Student">
   <property name="name" value="Setter"></property>
   <property name="ages" value="21"></property>
   <property name="address" value="江苏省南京市"></property>
   <property name="cost" value="20.00"></property>
   <property name="grade" ref="grade"></property>
</bean>

---TestStudent.java

package com.jty.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent
{
public static void main(String []agrs) {
//获取ioc容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student3=applicationContext.getBean(Student.class,"student3");
System.out.println("生成学生用户:"+student3);
}
}
输出:
=调用默认构造器====
生成学生用户:Student [name=Setter, ages=21, address=江苏省南京市, cost=20.0, grade=Grade [schoolName=第四中学, gradeName=二年级]]
注:创建Student对象实例时调用默认构造函数,之后调用setter方法初始化对象

五、p命名空间

注:在使用p命名空间注入之前必须先引入p命名空间约束

---applicationContext.xml

<bean id="grade" class="com.jty.testSpring.Grade">
   <constructor-arg name="schoolName" value="第四中学" type="java.lang.String"></constructor-arg>
   <constructor-arg name="gradeName" value="二年级" type="java.lang.String"></constructor-arg>
</bean>
<bean id="student4" class="com.jty.testSpring.Student"
    p:name="p命名"
    p:ages="30"
    p:address="江苏省南京市"
    p:cost="30.00"
    p:grade-ref="grade">
</bean>

---TestStudent.java

package com.jty.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent
{
public static void main(String []agrs) {
//获取ioc容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student4=applicationContext.getBean(Student.class,"student4");
System.out.println("生成学生用户:"+student4);
}
}
输出:
=调用默认构造器====
生成学生用户:Student [name=p命名, ages=30, address=江苏省南京市, cost=30.0, grade=Grade [schoolName=第四中学, gradeName=二年级]]

六、基于注解的注入

注:必须引入spring-context名称空间,使用类路径扫描和托管组件

注解释义对照在文末
---applicationContext.xml

 <context:component-scan base-package="com.jty.testSpring"></context:component-scan>

---Grade.java

package com.jty.testSpring;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("grade")
public class Grade {
@Value("第五中学")
private String schoolName;//学校名
@Value("一年级")
private String gradeName;//年级名

   public Grade() {
         super();
   }
   public Grade(String schoolName, String gradeName) {
         super();
         this.schoolName = schoolName;
         this.gradeName = gradeName;
   }
   /*getter、setter、toString略*/

}

---Student.java

package com.jty.testSpring;
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;
@Component("student5")
public class Student {
@Value("基于注解")
private String name;//姓名
@Value("40")
private int ages;//年龄
@Value("贵州省贵阳市")
private String address;//地址
@Value("50.00")
private double cost;//零花钱
@Autowired
@Qualifier("grade")
private Grade grade;
public Student() {
super();
System.out.println("=调用默认构造器");
this.name="用户1";
this.ages=20;
this.address="江苏省南京市";
this.cost=20.00;
this.grade=new Grade("第三中学","三年级");
}
public Student(String name, Integer ages, String address, Double cost, Grade grade) {
super();
System.out.println("
=调用带参构造器========");
this.name = name;
this.ages = ages;
this.address = address;
this.cost = cost;
this.grade = grade;
}
/getter、setter、toString略/
}

---TestStudent.java

package com.jty.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent
{
public static void main(String []agrs) {
//获取ioc容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student5=applicationContext.getBean(Student.class,"student5");
System.out.println("生成学生用户:"+student5);
}
}
输出:
=调用默认构造器====
生成学生用户:Student [name=基于注解, ages=40, address=贵州省贵阳市, cost=50.0, grade=Grade [schoolName=第五中学, gradeName=一年级]]

七、集合注入

---MyCollection.java

package com.jty.testSpring;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class MyCollection {
private String[] array;
private List list;
private Set set;
private Map<String,String> map;
private Properties pros;

   public MyCollection() {
         array=new String[5];
         list=new ArrayList<String>();
         set=new HashSet<String>();
         map=new HashMap<String, String>();
         pros=new Properties();
   }
   public String[] getArray() {
         return array;
   }
   public void setArray(String[] array) {
         this.array = array;
   }
   public List<String> getList() {
         return list;
   }
   public void setList(List<String> list) {
         this.list = list;
   }
   public Set<String> getSet() {
         return set;
   }
   public void setSet(Set<String> set) {
         this.set = set;
   }
   public Map<String, String> getMap() {
         return map;
   }
   public void setMap(Map<String, String> map) {
         this.map = map;
   }
   public Properties getPros() {
         return pros;
   }
   public void setPros(Properties pros) {
         this.pros = pros;
   }
   @Override
   public String toString() {
         return "MyCollection [\n array=" + Arrays.toString(array) + ",\n list=" + list + ",\n set=" + set + ",\n map=" + map + ",\n pros=" + pros + "]";
   }

}

---applicationContext.xml

"array 1""array 2""array 3""array 4""array 5"list 1list 2list 3list 4list 5set 1set 2set 3set 4set 5prop 1prop 2prop 3

---TestMyCollection.java

package com.jty.testSpring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMyCollection {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
MyCollection mycollection=applicationContext.getBean(MyCollection.class,"myCollection");
System.out.println(mycollection);
}
}
输出:
MyCollection [
array=["array 1", "array 2", "array 3", "array 4", "array 5"],
list=[list 1, list 2, list 3, list 4, list 5],
set=[set 1, set 2, set 3, set 4, set 5],
map={key1=map1, key2=map2, key3=map3},
pros={pros1=prop 1, pros3=prop 3, pros2=prop 2}]
总结Summary
使用哪一种注入方式,必须满足相应的前提
构造器注入-提供默认构造器
setter注入-提供setter方法
p命名空间-引入p命名空间
注解注入-引入context命名空间扫描类路径
type属性可省略,且只能使用包装类
普通值使用 value属性,引用值使用ref属性

注解
释义
@Component

@Component("beanId")

@Repository("beanId")//dao层
@Component("beanId")
@Service("beanId")//service层
@Component("beanId")
@Controller("beanId")//视图控制层
@Component("beanId")
@value("初始化值")

@Autowired
引用值按类型自动注入
@Autowired
@ Qualifier("引用变量名")

@Resource("引用变量名")//需要导入 javax.annotation.Resource

其它注解: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-annotation-config

上一篇:谷歌弃用 APK 格式!替代品 AAB 有何优势?


下一篇:SpringBoot启动会加载大量的自动配置类