Spring篇--02 Spring IOC
一、IOC(Inversion of Controll)控制反转
1.IOC是什么?
对象之间的依赖关系由容器来建立
2.DI(Dependency Injection 依赖注入)
容器通过调用对象的set方法或者构造器来建立依赖关系
注意:IOC是目标 DI是手段
3.set方式注入
step1:提供相应的set方法
step2:使用<property>元素
package ioc;
public class A {
private IB b;
public void setB(IB b) {
System.out.println("setB()方法执行了");
this.b = b;
}
public A() {
System.out.println("A()");
}
public void execute() {
b.f1();
System.out.println("execute()");
}
}
package ioc;
public class B implements IB {
public B() {
System.out.println("B()");
}
public void f1() {
System.out.println("B's f1()");
}
}
<bean id="b1" class="ioc.B"/>
<bean id="c1" class="ioc.C"/>
<!-- property元素:表示使用set方法来注入依赖关系
ref属性指定属性值(是被注入的bean的id) -->
<bean id="a1" class="ioc.A">
<property name="b" ref="c1"/>
</bean>
4.构造器方法注入
step1:添加相应的构造器
step2:配置constructor-arg元素
<bean id="b1" class="ioc2.B"/>
<!-- constructor-arg元素:用来配置构造器方式的注入,其中,index属性指定参数的下标 -->
<bean id="a1" class="ioc2.A">
<constructor-arg index="0" ref="b1"/>
</bean>
package ioc2;
public class B {
public B() {
System.out.println("B()");
}
public void f1() {
System.out.println("B's f1()");
}
}
package ioc2;
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 execute() {
b.f1();
System.out.println("execute");
}
}
5.自动装配
自动装配,指的是spring容器依据某种规则,自动建立对象之间的依赖关系。
注意:a.默认情况下,容器不会自动装配
b.可以通过指定autowire属性来告诉容器进行自动装配(容器仍然需要通过set方法或者构造器来完成依赖关系的建立)
<bean id="wt" class="ioc2.Waiter"/>
<!-- autowire属性:自动装配 。该属性有如下三个值
byName:容器依据属性名来查找响应的bean,然后调用对应的set方法来注入
注意:a.如果找不到对应的bean,注入空值。b.不可能找到多个符合条件的值
byType:容器依据属性类型找到对应的bean,然后调用对应的set方法来完成注入
注意:a.如果找不到对应的bean,注入null. b.有可能找到多个符合条件的bean,此时会出错
constructor:类似于byType -->
<bean id="rest" class="ioc2.Restaurant" autowire="byName"/>
package ioc2;
public class Waiter {
public Waiter() {
System.out.println("waiter()");
}
}
package ioc2;
public class Restaurant {
private Waiter wt;
public Restaurant() {
System.out.println("Restaurant()");
}
public void setWt(Waiter wt) {
System.out.println("set()");
this.wt = wt;
}
@Override
public String toString() {
return "Restaurant [wt=" + wt + "]";
}
}
6.注入基本类型的值
使用value属性即可
7.注入集合类型的值
List Set Map Properties
<?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:beans="http://www.springframework.org/schema/beans"
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:jms="http://www.springframework.org/schema/jms"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/mvc"
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/jms http://www.springframework.org/schema/tx/spring-jms-3.2.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/tx/spring-lang-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/tx/spring-mvc-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/util http://www.springframework.org/schema/tx/spring-util-3.2.xsd">
<bean id="vb1" class="value.ValueBean">
<property name="name" value="胡八一"/>
<property name="age" value="30"/>
<property name="city">
<list>
<value>北京</value>
<value>上海</value>
<value>深圳</value>
<value>广州</value>
</list>
</property>
<property name="interest">
<set>
<value>读书</value>
<value>看报</value>
<value>晒太阳</value>
</set>
</property>
<property name="score">
<map>
<entry key="english" value="100"/>
<entry key="math" value="100"/>
<entry key="chinese" value="100"/>
</map>
</property>
<property name="db">
<props>
<prop key="username">小花</prop>
<prop key="password">5210</prop>
</props>
</property>
</bean>
</beans>
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> city;
private Set<String> interest;
private Map<String, Double> score;
private Properties db;
public ValueBean() {
System.out.println("ValueBean()");
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setCity(List<String> city) {
this.city = city;
}
public void setDb(Properties db) {
this.db = db;
}
public void setScore(Map<String, Double> score) {
this.score = score;
}
public void setInterest(Set<String> interest) {
this.interest = interest;
}
@Override
public String toString() {
return "ValueBean [name=" + name + ", age=" + age + ", city=" + city + ", interest=" + interest + ", score="
+ score + ", db=" + db + "]";
}
}
8.引入方式注入集合类型的值
<!-- 将集合类型的值配置成一个bean -->
<util:list id="cityBean">
<value>上海</value>
<value>杭州</value>
<value>北京</value>
</util:list>
<util:set id="interestBean">
<value>书法</value>
<value>绘画</value>
<value>拳击</value>
</util:set>
<util:map id="scoreBean">
<entry key="english" value="97"/>
<entry key="math" value="98"/>
<entry key="chinese" value="99"/>
</util:map>
<util:properties id="dbBean">
<prop key="username">小草</prop>
<prop key="password">0220</prop>
</util:properties>
<!-- 引用的方式注入集合类型的值 -->
<bean id="vb2" class="value.ValueBean">
<property name="city" ref="cityBean"/>
<property name="interest" ref="interestBean"/>
<property name="score" ref="scoreBean"/>
<property name="db" ref="dbBean"/>
</bean>
9.读取properties的值
<!-- 读取properties文件的内容
classpath:按照类路径来搜索
spring容器会依据路径找到对应的properties文件,然后读取该文件的内容到Properties对象 -->
<util:properties id="config" location="classpath:config.properties"/>
10.使用spring表达式
可以使用spring表达式读取其他bean的属性,它的语法类似于el表达式
<bean id="sp1" class="value.SpelBean">
<property name="name" value="#{vb1.name}"/>
<property name="city" value="#{vb1.city[1]}"/>
<property name="score" value="#{vb1.score.math}"/>
<property name="pageSize" value="#{config.pagesize}"/>
</bean>
二、使用注解简化配置
1.组件扫描
spring容器在启动之后,会扫描指定的包及其子包下面的所有的类,如果该类前面有特定的注解(比如@Component),则spring容器会将这个类纳入容器进行管理(相当于在配置文件当中,配置了一个bean元素)。
2.如何进行组件扫描
step1:在类前添加特定的注解
注:除了@Component注解,还有@Service,@Repository和@Controller,作用是等价的,只不过有语义上的差异。
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("sb1") //组件bean
@Scope("singleton") //指定作用域
@Lazy(true) //延迟加载
//单例
public class SomeBean {
@PostConstruct
public void init() {
System.out.println("init()");
}
@PreDestroy
public void destory() {
System.out.println("destory");
}
public SomeBean() {
System.out.println("SomeBean()");
}
}
step2:要在配置文件中,添加组件扫描的配置
<!-- 配置组件扫描 -->
<!--
base-package属性:指定要扫描的包名,spring容器会扫描该包及其子包
下面的所有的类,如果该类前面有特定的注解(@Component),则spring容器 会将其
纳入容器进行管理(相当于这儿配置了一个bean元素)。
-->
<context:component-scan base-package="annotation"/>
3.依赖注入相关的注解
@Autowired和@Qualifier
a.该注解支持set方式注入和构造器方式的注入
b.当采用set方式注入时,可以将@Autowired添加到set方法前面,如果不使用@Qualifier,则容器会采用byType的方式来注入,有可能出错,所以建议使用@Quarlifer注解,明确指定要注入的bean的id。
注:也可以将这两个注解直接添加到属性前
c.当采用构造器注入时,可以 将该注解添加到对应的构造器前面即可。
package annotation;
import org.springframework.stereotype.Component;
@Component("wt")
public class Waiter {
public Waiter() {
System.out.println("Waiter()");
}
}
package annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("rt")
public class Restaurant {
@Autowired
@Qualifier("wt")
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 + "]";
}
}
<?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:beans="http://www.springframework.org/schema/beans"
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:jms="http://www.springframework.org/schema/jms"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/mvc"
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/jms http://www.springframework.org/schema/tx/spring-jms-3.2.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/tx/spring-lang-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/tx/spring-mvc-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/util http://www.springframework.org/schema/tx/spring-util-3.2.xsd">
<context:component-scan base-package="annotation"/>
</beans>
@Test
//测试@Autowired(set方式注入)
public void test1() {
ApplicationContext ac=new ClassPathXmlApplicationContext("annotation.xml");
Restaurant rt = ac.getBean("rt",Restaurant.class);
System.out.println(rt);
}
@Resource
a.只支持set方式的注入
b.可以将该注解添加到属性前 ,使用name属性指定要注入的bean的id(如果不指定,会按照byType的方式注入)
注:也可以将该注解添加到属性前
package annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
@Component("bar")
public class Bar {
private Waiter wt;
public Bar() {
System.out.println("Bar()");
}
@Resource(name="wt")
public void setWt(Waiter wt) {
System.out.println("setWt()");
this.wt = wt;
}
@Override
public String toString() {
return "Bar [wt=" + wt + "]";
}
}
4.@Value注解
a.可以使用该注解来注入基本类型的值
b.也可以使用该注解来使用spring表达式
c.该注解可以添加到属性前,或者添加到对应的set方法前
package annotation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("mg")
public class Manager {
@Value("#{config.pagesize}")
private String pageSize;
@Value("小草")
private String name;
@Override
public String toString() {
return "Manager [pageSize=" + pageSize + ", name=" + name + "]";
}
public Manager() {
System.out.println("Manager()");
}
}