Unit02: 参数值注入 、 基于注解的组件扫描
(4)IOC (Inversion Of Controll 控制反转)
什么是IOC?
对象之间的依赖关系由容器来建立。
什么是DI? (Dependency Injection 依赖注入)
容器通过调用set方法或者构造器来建立对象之间的依赖关系。
注: IOC是目标,而DI是手段。
依赖注入的两种方式
方式一 set方法注入。
step1. 添加set方法。
step2. 配置set方法注入。
方式二 构造器注入。
step1. 添加构造器。
step2. 配置构造器注入。
自动装配 (了解)
什么是自动装配?
容器依据某些规则,自动建立对象之间的依赖关系。
注:默认情况下,容器禁止自动装配。
注入基本类型的值
使用value属性来注入。
注入集合类型的值
List,Set,Map,Properties
引用的方式注入集合类型的值
读取properties文件的内容
使用Spring表达式
案例:
auto
package auto; public class Restaurant { private Waiter wt; public void setWt(Waiter wt) { System.out.println("setWt()"); this.wt = wt; } public Restaurant() { System.out.println("Restaurant"); } @Override public String toString() { return "Restaurant [wt=" + wt + "]"; } }
package auto; public class Waiter { public Waiter() { System.out.println("Waiter()"); } }
ioc
package ioc; public class A { private B b; public A() { System.out.println("A()"); } public A(B b) { System.out.println("A(B)"); this.b = b; } public void service(){ System.out.println("A's service()"); b.f1(); } }
package ioc; public class B { public B() { System.out.println("B()"); } public void f1(){ System.out.println("B's f1()"); } }
value
package value; public class SpelBean { private String name; private String interest; private double score; private int pageSize; public void setPageSize(int pageSize) { this.pageSize = pageSize; } public SpelBean() { System.out.println("SpelBean"); } public void setScore(double score) { this.score = score; } public void setInterest(String interest) { this.interest = interest; } public void setName(String name) { this.name = name; } @Override public String toString() { return "SpelBean [name=" + name + ", interest=" + interest + ", score=" + score + ", pageSize=" + pageSize + "]"; } }
package value; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class ValueBean { private String name; private int age; private List<String> interest; private Set<String> city; private Map<String,Double> score; private Properties db; public String getName() { return name; } public int getAge() { return age; } public List<String> getInterest() { return interest; } public Set<String> getCity() { return city; } public Map<String, Double> getScore() { return score; } public Properties getDb() { return db; } public void setInterest(List<String> interest) { this.interest = interest; } public void setDb(Properties db) { this.db = db; } public void setCity(Set<String> city) { this.city = city; } public void setScore(Map<String, Double> score) { this.score = score; } public ValueBean() { System.out.println("ValueBean()"); } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "ValueBean [name=" + name + ", age=" + age + ", interest=" + interest + ", city=" + city + ", score=" + score + ", db=" + db + "]"; } }
src/main/resource
<?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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <bean id="wt2" class="auto.Waiter"/> <!-- autowire指定自动装配的规则,有这样三个值: byName: 容器依据属性名查找对应的bean(即 bean的id等于属性名),找到之后,调用对应的 set方法来完成注入。 注:如果找不到,会注入null值。 byType:容器依据属性类型查找对应的bean(即 bean的类型与属性类型一致),找到之后,调用对 应的set方法来完成注入。 注:如果找不到,会注入null值。 如果找到多个,会出错。 constructor:类似byType,只不过会调用构造器 来完成注入。 --> <bean id="rest" class="auto.Restaurant" autowire="byType"/> </beans>
pagesize=10
<?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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <bean id="b1" class="ioc.B"/> <!-- 构造器方式注入。 index属性:指定参数的下标(从0开始) --> <bean id="a1" class="ioc.A"> <constructor-arg index="0" ref="b1"/> </bean> </beans>
<?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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <!-- 使用Spring表达式读取其它bean的属性值。 --> <bean id="sb1" class="value.SpelBean"> <property name="name" value="#{vb1.name}"/> <property name="interest" value="#{vb1.interest[0]}"/> <property name="score" value="#{vb1.score['英语']}"/> <property name="pageSize" value="#{config.pagesize}"/> </bean> <bean id="vb1" class="value.ValueBean"> <property name="name" value="小月"/> <property name="age" value="22"/> <property name="interest"> <list> <value>钓鱼</value> <value>旅游</value> <value>看电视</value> <value>看电视</value> </list> </property> <property name="city"> <set> <value>北京</value> <value>长沙</value> <value>南京</value> </set> </property> <property name="score"> <map> <entry key="英语" value="60"/> <entry key="math" value="80"/> </map> </property> <property name="db"> <props> <prop key="username">King</prop> <prop key="password">1234</prop> </props> </property> </bean> <!-- 引用的方式注入集合类型的值 --> <util:list id="interestBean"> <value>钓鱼</value> <value>旅游</value> <value>上网</value> </util:list> <util:set id="cityBean"> <value>北京</value> <value>上海</value> <value>武汉</value> </util:set> <util:map id="scoreBean"> <entry key="english" value="80"/> <entry key="math" value="90"/> </util:map> <util:properties id="dbBean"> <prop key="username">King</prop> <prop key="password">1234</prop> </util:properties> <bean id="vb2" class="value.ValueBean"> <property name="interest" ref="interestBean"/> <property name="city" ref="cityBean"/> <property name="score" ref="scoreBean"/> <property name="db" ref="dbBean"/> </bean> <!-- 读取properties文件的内容 --> <!-- location属性:指定要 读取的文件的位置, 其中,classpath:表示依据类路径去查找。 --> <util:properties id="config" location="classpath:config.properties"/> </beans>
src/test/java
test
package test; import java.util.Properties; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import auto.Restaurant; import ioc.A; import value.SpelBean; import value.ValueBean; public class TestCase { @Test // 测试 构造器方式的注入 public void test1() { // 启动Spring容器 String config = "ioc.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); // 获得对象 A a1 = ac.getBean("a1", A.class); a1.service(); } @Test // 测试 自动装配 public void test2() { // 启动Spring容器 String config = "auto.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); // 获得对象 Restaurant rest = ac.getBean("rest", Restaurant.class); System.out.println(rest); } @Test // 测试 注入基本类型的值 public void test3() { // 启动Spring容器 String config = "value.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); ValueBean vb1 = ac.getBean("vb2", ValueBean.class); System.out.println(vb1); } @Test // 读取properties文件 public void test4() { // 启动Spring容器 String config = "value.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); Properties props = ac.getBean("config", Properties.class); System.out.println(props); } @Test // 测试 Spring表达式 public void test5() { // 启动Spring容器 String config = "value.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext( config); SpelBean sb1 = ac.getBean("sb1",SpelBean.class); System.out.println(sb1); } }
使用注解简化配置
(1)什么是组件扫描?
Spring容器会扫描base-package指定的包及其子包下面的所有的类, 如果这些类前面有一些特殊的注解(比如@Component),则Spring 容器会将这些类纳入容器进行管理(相当于在配置文件当中有对应的bean)。
(2)如何进行组件扫描?
step1. 在类前面添加特定的注解。比如 @Component。
step2. 在配置文件当中,配置组件扫描。
(3)作用域和延迟加载相关注解
(4)依赖注入相关的注解
(5)value注解
案例:
annotation
package annotation; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component("eb") public class ExampleBean { @Value("小月") private String name; @Value("#{config.pagesize}") private int pageSize; public void setPageSize(int pageSize) { this.pageSize = pageSize; } public ExampleBean() { System.out.println("ExampleBean()"); } public void setName(String name) { this.name = name; } @Override public String toString() { return "ExampleBean [name=" + name + ", pageSize=" + pageSize + "]"; } }
package annotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("mg") public class Manager { private Waiter wt; public Manager() { System.out.println("Manager()"); } @Autowired public Manager(@Qualifier("wt") Waiter wt) { System.out.println("Manager(wt)"); this.wt = wt; } @Override public String toString() { return "Manager [wt=" + wt + "]"; } }
package annotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("rest") public class Restaurant { @Autowired @Qualifier("wt") private Waiter wt; // @Autowired // public void setWt(@Qualifier("wt") Waiter wt) { // System.out.println("setWt()"); // this.wt = wt; // } @Override public String toString() { return "Restaurant [wt=" + wt + "]"; } public Restaurant() { System.out.println("Restaurant()"); } }
package annotation; import javax.annotation.Resource; import org.springframework.stereotype.Component; @Component("school") public class School { private Waiter wt; @Resource(name="wt") public void setWt(Waiter wt) { System.out.println("setWt()"); this.wt = wt; } public School() { System.out.println("School()"); } @Override public String toString() { return "School [wt=" + wt + "]"; } }
package annotation; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component("stu1") @Scope("singleton") @Lazy(true) public class Student { public Student() { System.out.println("Student()"); } @PostConstruct public void init(){ System.out.println("init()"); } @PreDestroy public void destroy(){ System.out.println("destroy()"); } }
package annotation; import org.springframework.stereotype.Component; @Component("wt") public class Waiter { public Waiter() { System.out.println("Waiter()"); } }
src/main/resources
<?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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <!-- 配置组件扫描 --> <!-- Spring容器会扫描base-package指定的包及 其子包下面的所有的类,如果这些类前面有一 些特殊的注解(比如@Component),则Spring 容器会将这些类纳入容器进行管理(相当于在 配置文件当中有对应的bean)。 --> <context:component-scan base-package="annotation"/> <util:properties id="config" location="classpath:config.properties"/> </beans>
pagesize=10
src/test/java
test
package test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import annotation.ExampleBean; import annotation.Manager; import annotation.Restaurant; import annotation.School; import annotation.Student; public class TestCase { @Test //测试 组件扫描 public void test1(){ String config = "annotation.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext( config); Student stu1 = ac.getBean("stu1", Student.class); System.out.println(stu1); } @Test //测试 作用域 public void test2(){ String config = "annotation.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext( config); Student stu1 = ac.getBean("stu1", Student.class); Student stu2 = ac.getBean("stu1", Student.class); System.out.println(stu1 == stu2); } @Test // 测试 生命周期 public void test3(){ String config = "annotation.xml"; AbstractApplicationContext ac = new ClassPathXmlApplicationContext( config); Student stu1 = ac.getBean("stu1", Student.class); ac.close(); } @Test // 测试 延迟加载 public void test4(){ String config = "annotation.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext( config); } @Test // 测试 @Autowired和 @Qualifier public void test5(){ String config = "annotation.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext( config); Restaurant rest = ac.getBean("rest",Restaurant.class); System.out.println(rest); Manager mg = ac.getBean("mg",Manager.class); System.out.println(mg); } @Test //测试 @Resource public void test6(){ String config = "annotation.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext( config); School s = ac.getBean("school", School.class); System.out.println(s); } @Test //测试 @Value public void test7(){ String config = "annotation.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext( config); ExampleBean eb = ac.getBean("eb",ExampleBean.class); System.out.println(eb); } }