本文主要介绍Spring框架中IOC的简单使用。
1. 构建简单的Spring框架的演示Demo
-
默认配置文件:applicationContext.xml
-
Spring的核心包
- Commons-logging.jar
- Spring-beans.jar
- Spring-Context.jar
- Spring-Core.jar
- Spring-expression.jar
2. 演示代码搭建
2.1. Meavn的Pom配置文件配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringDemo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>SpringLearn</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2.2. IOC代码
- Main函数代码
static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public static void main(String[] args) {
IOCDemoClass iocDemoClass = (IOCDemoClass)contextgetBean("IOCDemoClass");
System.out.println(ToStringBuilder.reflectionToStrin(iocDemoClass));
System.out.println("--------------------------作用--------------------------");
System.out.println("单例singleton");
for (int i=0;i<10;i++) {
IOCDemoClass iocDemoClassObject = (IOCDemoClasscontext.getBean("IOCDemoClass");
System.out.println(iocDemoClassObject);
}
System.out.println("原型prototype");
for (int i=0;i<10;i++) {
IOCDemoClass iocDemoClassObject = (IOCDemoClasscontext.getBean("IOCDemoClass_prototype");
System.out.println(iocDemoClassObject);
}
System.out.printl("--------------------------List-------------------------");
List<String> list=(List<String>) context.getBea("bookList");
System.out.println(list);
System.out.printl("--------------------------maps-------------------------");
Map<String,String> map=(Map<String,String>) contextgetBean("maps");
System.out.println(map);
System.out.printl("--------------------------sets-------------------------");
Set<String> set=(Set<String>) context.getBean("sets";
System.out.println(set);
}
- IOCDemoClass类代码结构
package icoClass;
import org.springframework.context.annotation.Scope;
/**
* @Classname IOCDemoClass
* @Description IOC依赖注入测试类
* @Date 2021/5/24 12:40
* @Created by xiaocai
*/
public class IOCDemoClass {
/**
* 名称
*/
private String strName="";
public String getStrName() {
return strName;
}
public void setStrName(String strName) {
this.strName = strName;
}
/**
* 年龄
*/
private Integer iAge;
public Integer getiAge() {
return iAge;
}
public void setiAge(Integer iAge) {
this.iAge = iAge;
}
public IOCDemoClass(String strName, Integer iAge) {
this.strName = strName;
this.iAge = iAge;
}
/**
* 描述信息
*/
private String DescInfo="";
public String getDescInfo() {
return DescInfo;
}
public void setDescInfo(String descInfo) {
DescInfo = descInfo;
}
}
- 代码导出结果:
icoClass.IOCDemoClass@1e0b4072[DescInfo=小菜同学属性注入测试,iAge=26,strName=xiaocai]
--------------------------作用域--------------------------
单例singleton
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
icoClass.IOCDemoClass@1e0b4072
原型prototype
icoClass.IOCDemoClass@d86a6f
icoClass.IOCDemoClass@2892d68
icoClass.IOCDemoClass@5ab956d7
icoClass.IOCDemoClass@3646a422
icoClass.IOCDemoClass@750e2b97
icoClass.IOCDemoClass@3e27aa33
icoClass.IOCDemoClass@2e385cce
icoClass.IOCDemoClass@2ddc9a9f
icoClass.IOCDemoClass@298a5e20
icoClass.IOCDemoClass@2a7f1f10
--------------------------List--------------------------
[老人与海, 平凡的世界, 阿甘正传]
--------------------------maps--------------------------
{Java=java, C++=c++}
--------------------------sets--------------------------
[[北京, 上海]]
Disconnected from the target VM, address: '127.0.0.1:55374', transport: 'socket'
Process finished with exit code 0
3. 结合代码解释相关概念
3.1 作用域
默认情况下IOC容器生成的对象是单例的,作用域分为:
- singleton单例模式,
全局有且仅有一个实例
- prototype原型模式,
每次获取Bean的时候会有一个新的实例
- request
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效,
- session
session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
- global session
global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个 portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。如果你在web中使用global session作用域来标识bean,那么web会自动当成session类型来使用。
3.2 相关关键字
3.2.1. lazy-init=true:懒加载
- 修改配置文件
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id='IOCDemoClass' class='icoClass.IOCDemoClass'>
<constructor-arg name="strName" value='xiaocai' />
<constructor-arg name="iAge" value='26' />
<property name="DescInfo" value="小菜同学属性注入测试"></property>
</bean>
<bean id='MyCalculator' class='calc.MyCalculator'>
</bean>
</beans>
- 增加构造函数输出以及Main函数
public class MyCalculator implements ICalculator {
public MyCalculator() {
System.out.println("MyCalculator初始化");
}
}
public class IOCDemoClass {
public IOCDemoClass(String strName, Integer iAge) {
this.strName = strName;
this.iAge = iAge;
System.out.println("IOCDemoClass初始化");
}
}
static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public static void main(String[] args) {
lazyinitShowInfo();
}
private static void lazyinitShowInfo() {
System.out.println("----------------------------applicationContext创建-------------------------------");
IOCDemoClass iocDemoClass = (IOCDemoClass)context.getBean("IOCDemoClass");
System.out.println(ToStringBuilder.reflectionToString(iocDemoClass));
MyCalculator myCalc = (MyCalculator)context.getBean("MyCalculator");
System.out.println(ToStringBuilder.reflectionToString(myCalc));
}
- 饿汉输出信息
输出信息
IOCDemoClass初始化
MyCalculator初始化
----------------------------applicationContext创建-------------------------------
icoClass.IOCDemoClass@1e0b4072[DescInfo=小菜同学属性注入测试,iAge=26,strName=xiaocai]
calc.MyCalculator@63376bed[]
- 调整对象为懒汉加载模式
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id='IOCDemoClass' class='icoClass.IOCDemoClass' lazy-init="true">
<constructor-arg name="strName" value='xiaocai' />
<constructor-arg name="iAge" value='26' />
<property name="DescInfo" value="小菜同学属性注入测试"></property>
</bean>
<bean id='MyCalculator' class='calc.MyCalculator' lazy-init="true">
</bean>
</beans>
- 懒汉输出信息
----------------------------applicationContext创建-------------------------------
IOCDemoClass初始化
icoClass.IOCDemoClass@5677323c[DescInfo=小菜同学属性注入测试,iAge=26,strName=xiaocai]
MyCalculator初始化
calc.MyCalculator@1a6d8329[]
3.2.2. depends-on=“B” 依赖加载
static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public static void main(String[] args) {
depends_on();
}
private static void depends_on() {
System.out.println("----------------------------applicationContext创建-------------------------------");
MyCalculator myCalc = (MyCalculator)context.getBean("MyCalculator");
System.out.println(ToStringBuilder.reflectionToString(myCalc));
System.out.println(ToStringBuilder.reflectionToString(myCalc.getRefIOCDemoClass()));
}
Connected to the target VM, address: '127.0.0.1:64132', transport: 'socket'
----------------------------applicationContext创建-------------------------------
MyCalculator初始化
IOCDemoClass初始化
calc.MyCalculator@65c7a252[refIOCDemoClass=icoClass.IOCDemoClass@6574a52c]
icoClass.IOCDemoClass@6574a52c[DescInfo=小菜同学属性注入测试,iAge=26,strName=xiaocai]
Disconnected from the target VM, address: '127.0.0.1:64132', transport: 'socket'
Process finished with exit code 0
3.2.3. default-autowire=“byname”/“byType” 自动装配
default-autowire与autowire主要用于spring的IOC的注解注入
-
在beans标签设置default-autowire=”byName”后,在spring容器实例化bean(包含xml配置bean和注解方式bean)时,该bean内部的字段会自动根据byName装载spring容器里的bean。
-
@Autowired 自动创建
<?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:util="http://www.springframework.org/schema/util"
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/util
https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<bean id='IOCDemoClass' class='icoClass.IOCDemoClass' lazy-init="true">
<constructor-arg name="strName" value='xiaocai' />
<constructor-arg name="iAge" value='26' />
<property name="DescInfo" value="小菜同学属性注入测试"></property>
</bean>
<bean id='MyCalculator' class='calc.MyCalculator' lazy-init="true">
<!--<property name="refIOCDemoClass" ref="IOCDemoClass"></property>-->
</bean>
</beans>
static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public static void main(String[] args) {
autowireObject();
}
private static void autowireObject() {
System.out.println("----------------------------applicationContext创建-------------------------------");
MyCalculator myCalc = (MyCalculator)context.getBean("MyCalculator");
System.out.println(ToStringBuilder.reflectionToString(myCalc.getRefIOCDemoClass()));
}
Connected to the target VM, address: '127.0.0.1:63755', transport: 'socket'
----------------------------applicationContext创建-------------------------------
MyCalculator初始化
IOCDemoClass初始化
icoClass.IOCDemoClass@1cf56a1c[DescInfo=小菜同学属性注入测试,iAge=26,strName=xiaocai]
Disconnected from the target VM, address: '127.0.0.1:63755', transport: 'socket'
3.2.3. @Component 标记对象类纳入Spring管理
3.2.4. @Qualifier、@Service、@Controller等同于@Component,通过使用 @Qualifier 注解,我们可以消除需要注入哪个 bean 的问题。
3.2.5. @Value(“xxx”) 默认值
3.2.6. @Primary
自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常。(只对接口的多个实现生效)
3.2.7. factory-bean和factory-method
- factory-bean 表示使用的工厂类
- factory-method 表示工厂类使用的函数