IOC : 控制反转 Inversion of Controller,IOC本质上是一个概念,是一种思想,控制反转就是对对象控制权的转移,SpringIOC容器创建对象,然后将对象的使用权交出去。
基于XML配置文件方式的使用
使用maven
引入Spring相关的依赖
<properties>
<java.version>1.8</java.version>
<spring.verson>5.3.9</spring.verson>
<junit.version>5.7.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.verson}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
创建 UserBean.java
package org.spring.ss.pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class UserBean {
private String name;
private Integer age;
private String[] favorites;
public UserBean(String name, Integer age) {
this.name = name;
this.age = age;
}
public void say() {
System.out.println("say");
}
}
在 resources
中添加spring
配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.spring.ss.pojo.UserBean" id="userBean"/>
</beans>
测试
/**
* IoC的方式获取 UserBean 对象
*/
@Test
public void sayTestIoc() {
// ioc 容器初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// ioc 通过bean 的 id 获取指定的bean
UserBean userBean = (UserBean) applicationContext.getBean("userBean");
// 使用bean
userBean.say();
}
从容器中获取对象的方式
-
根据ID获取,
IOC
容器中同一个bean
只有一个id
-
根据
name
获取,IOC
容器中同一个bean
可以声明一个或者多个name
<!-- id只能声明一个,name可以通过逗号、分号、空格分割声明多个 --> <bean class="org.spring.ss.pojo.UserBean" id="userBean" name="userBean2,u,uu"/> <bean class="org.spring.ss.pojo.UserBean" id="userBean3"/>
-
根据类型,可以根据需要获取的对象的类型从容器中获取对象
@Test public void sayTestIoc2() { // ioc 容器初始化 , 调用UserBean中无参构造器创建对象 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserBean userBean = applicationContext.getBean(UserBean.class); // 使用bean userBean.say(); }
如果同一类型的对象在容器中有多个,这个时候只根据类型来查找,程序就会报错。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- id只能声明一个,name可以通过逗号、分号、空格分割声明多个 --> <bean class="org.spring.ss.pojo.UserBean" id="userBean" name="userBean2,u,uu"/> <bean class="org.spring.ss.pojo.UserBean" id="userBean3"/> </beans>
这时候,只能通过getBean
方法中的组合条件查找。@Test public void sayTestIoc3() { // ioc 容器初始化 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // ioc 根据 类型 获取指定的bean, 通过类型获取的时候,如果同一类型的 bean 有多个,会报错 // UserBean userBean = applicationContext.getBean(UserBean.class); // 可以组合条件查找 UserBean userBean = applicationContext.getBean("userBean3", UserBean.class); // 使用bean userBean.say(); }
另外,还可以在
<bean>
中设置primary
属性为true
,那么当同一类型有多个对象时,会优先返回primary
属性所在的对象<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- id只能声明一个,name可以通过逗号、分号、空格分割声明多个 --> <bean class="org.spring.ss.pojo.UserBean" id="userBean" name="userBean2,u,uu"/> <bean class="org.spring.ss.pojo.UserBean" id="userBean3"/> <!-- 如果同一类型的对象有多个,可以通过 primary 来指定优先级 --> <bean class="org.spring.ss.pojo.UserBean" id="userBean4" primary="true"/> </beans>
工厂注入
静态工厂注入
StaticFactory.java
package org.spring.ss.factory;
import org.spring.ss.pojo.UserBean;
public class StaticFactory {
/**
* 静态工厂提供的方法
*
* @return
*/
public static UserBean getInstance() {
return new UserBean("Jupiter", 18);
}
}
在 applicationContext.xml
中添加配置
<!-- 静态工厂注入 -->
<bean id="userBean5" class="org.spring.ss.factory.StaticFactory" factory-method="getInstance"/>
junit test
@Test
public void sayTestIoc5() {
// ioc 容器初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBean userBean = applicationContext.getBean("userBean5", UserBean.class);
System.out.println(userBean);
}
输出:
UserBean(name=Jupiter, age=18)
动态工厂注入
DynamicFactory.java
package org.spring.ss.factory;
import org.spring.ss.pojo.UserBean;
public class DynamicFactory {
public UserBean getUserBean() {
return new UserBean("join", 13);
}
public UserBean getUserBean2() {
return new UserBean("chai", 15);
}
}
在 applicationContext.xml
中添加配置
<!-- 动态工厂注入 -->
<bean class="org.spring.ss.factory.DynamicFactory" id="dynamicFactory"/>
<bean id="userBean6" factory-bean="dynamicFactory" factory-method="getUserBean"/>
<bean id="userBean7" factory-bean="dynamicFactory" factory-method="getUserBean2"/>
junit test
@Test
public void sayTestIoc6() {
// ioc 容器初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBean userBean1 = applicationContext.getBean("userBean6", UserBean.class);
UserBean userBean2 = applicationContext.getBean("userBean7", UserBean.class);
System.out.println(userBean1);
System.out.println(userBean2);
}
输出:
UserBean(name=join, age=13)
UserBean(name=chai, age=15)
属性注入【DI】
属性注入主要是指如何给对象中的属性赋值
构造注入
构造注入, 构造注入需要提供对应的有参构造方法
在applicationContext.xml
中添加配置
<!-- 构造注入, 构造注入需要提供对应的有参构造方法 -->
<bean id="userBean8" class="org.spring.ss.pojo.UserBean">
<constructor-arg name="name" value="DIByConstructor"/>
<constructor-arg name="age" value="10"/>
<!--还可以通过 index 指定参数顺序的方式-->
<!--<constructor-arg index="0" value="DIByConstructor"/>
<constructor-arg index="1" value="10"/>-->
</bean>
添加测试方法
@Test
public void testDI() {
// ioc 容器初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBean userBean = applicationContext.getBean("userBean8", UserBean.class);
System.out.println(userBean);
}
输出:UserBean(name=DIByConstructor, age=10)
设置注入
在applicationContext.xml
中添加配置
<!-- 设置注入 -->
<bean id="userBean9" class="org.spring.ss.pojo.UserBean">
<property name="name" value="DIBySet"/>
<property name="age" value="20"/>
</bean>
添加测试方法
@Test
public void testDI2() {
// ioc 容器初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBean userBean = applicationContext.getBean("userBean9", UserBean.class);
System.out.println(userBean);
}
输出:UserBean(name=DIBySet, age=20)
简化构造注入和设值注入的操作
引入对应的名称空间
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
applicationContext.xml
的配置也可以写成这样:
<!--属性注入【DI】-->
<!-- 构造注入, 构造注入需要提供对应的有参构造方法 -->
<!--<bean id="userBean8" class="org.spring.ss.pojo.UserBean">
<constructor-arg name="name" value="DIByConstructor"/>
<constructor-arg name="age" value="10"/>
<!–还可以通过 index 指定参数顺序的方式–>
<!–<constructor-arg index="0" value="DIByConstructor"/>
<constructor-arg index="1" value="10"/>–>
</bean>-->
<!-- 构造注入 的 简化写法 -->
<bean id="userBean8" class="org.spring.ss.pojo.UserBean" c:_0="DIByConstructor" c:_1="10" />
<!-- 设置注入 -->
<!--<bean id="userBean9" class="org.spring.ss.pojo.UserBean">
<property name="name" value="DIBySet"/>
<property name="age" value="20"/>
</bean>-->
<!-- 简化写法 -->
<bean id="userBean9" class="org.spring.ss.pojo.UserBean" p:age="20" p:name="DIBySet"/>
其他类型的注入写法
创建Cat.java
package org.spring.ss.pojo;
import lombok.Data;
@Data
public class Cat {
private String color;
private String nick;
}
修改UserBean.java
为:
package org.spring.ss.pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@Data
@NoArgsConstructor
public class UserBean {
private String name;
private Integer age;
private String[] favorites;
private List<Cat> cats;
private Map<String, Object> map;
private Properties props;
public UserBean(String name, Integer age) {
this.name = name;
this.age = age;
}
public void say() {
System.out.println("say");
}
}
使用applicationContext.xml
进行设置属性
<!-- 设置注入 -->
<bean id="userBean10" class="org.spring.ss.pojo.UserBean">
<property name="name" value="DIBySet"/>
<property name="age" value="20"/>
<property name="favorites">
<array>
<value>篮球</value>
<value>爬山</value>
<value>逛街</value>
</array>
</property>
<property name="cats">
<list>
<bean class="org.spring.ss.pojo.Cat">
<property name="color" value="红色"/>
<property name="nick" value="肥猫"/>
</bean>
<bean class="org.spring.ss.pojo.Cat">
<property name="color" value="黄色"/>
<property name="nick" value="咖啡毛"/>
</bean>
</list>
</property>
<property name="map">
<map>
<entry key="name1" value="张三1"/>
<entry key="name2" value="张三2"/>
<entry key="name3" value="张三3"/>
</map>
</property>
<property name="props">
<props>
<prop key="username">root</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
添加测试方法
@Test
public void testDI3() {
// ioc 容器初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBean userBean = applicationContext.getBean("userBean10", UserBean.class);
System.out.println(userBean);
}
输出:UserBean(name=DIBySet, age=20, favorites=[篮球, 爬山, 逛街], cats=[Cat(color=红色, nick=肥猫), Cat(color=黄色, nick=咖啡毛)], map={name1=张三1, name2=张三2, name3=张三3}, props={password=123, username=root})