文章目录
简单记录 Spring5企业级开发实战 周冠亚,黄文毅著- 和 Spring5最新完整教程IDEA版-秦疆
Spring IoC的实现方式
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象(容器中获取Bean)。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
一个程序、对象创建方式、配置说明
导入Jar包
注 : spring 需要导入commons-logging进行日志记录 . 我们利用maven , 他会自动下载对应的依赖项 .
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.22.RELEASE</version>
</dependency>
https://repo.spring.io/release/org/springframework/spring/
创建一个空白maven项目实现IoC。
XML方式实现
XML方式实现用构造器方式实现IoC分为无参构造器和有参构造器两种。
通过无参构造方法来创建
User使用无参构造器的方式,实现无参构造器的IoC。
1、编写一个User实体类
User类的实现如下:
User.java
package com.test.ioc.xml;
/**
* 无参构造器实现IoC
*/
public class User {
/**
* 姓名
*/
private String name;
/**
* 无参构造器
*/
public User () {
System.out.println("user无参构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
/**
* 显示姓名
*/
public void showName(){
System.out.println("我叫 " + name +",哈哈!");
}
/**
* 说话的方法
*/
public void say() {
System.out.println("大家好!");
}
}
2、编写我们的spring文件
编写我们的spring文件 , 这里我们命名为spring-chapter2.xml
在resources下spring-chapter2.xml文件中,通过bean标签将User类交给IoC容器管理,代码如下:
<?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就是java对象 , 由Spring创建和管理-->
<!-- User无参构造器 -->
<bean id="user" class="com.test.ioc.xml.User">
<property name="name" value="柳小子"/>
</bean>
</beans>
3、测试类 UserTest.java
我们可以去进行测试了,哈哈
UserTest.java
package ioc.xml;
import com.test.ioc.xml.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Liu Awen Email:[email protected]
* @create 2020-01-14 9:47 AM
*/
public class UserTest {
@Test
public void test(){
//解析beans.xml文件 , 生成管理相应的Bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring-chapter2.xml");
//getBean : 参数即为spring配置文件中bean的id .
User user = (User) context.getBean("user");
user.say();
user.showName();
}
}
4、测试结果
D:\Environments\jdk-11.0.2\bin\java.exe...
user无参构造方法
大家好!
我叫 柳小子,哈哈!
Process finished with exit code 0
结果可以发现,在调用showName方法之前,User对象已经通过无参构造初始化了!
User使用无参构造器的方式,实现无参构造器的IoC。
OK , 到了现在 , 我们彻底不用再去程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !
思考
-
user 对象是谁创建的 ?
【 user 对象是由Spring创建的 】
-
user 对象的属性是怎么设置的 ?
【user 对象的属性是由Spring容器设置的 】
这个过程就叫控制反转(IoC) :
- 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的
- 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
依赖注入 : 就是利用set方法来进行注入的.
IOC是一种编程思想,由主动的编程变成被动的接收
可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .
通过有参构造方法来创建
与User类不同的是,Order类是没有无参构造器的,Order类含有一个带有两个参数——订单号和订单金额的有参构造器。
1、Order.java
Order类的定义如下:
package com.test.ioc.xml;
/**
* 有参构造器实现IoC
*/
public class Order implements Deliverable {
/**
* 订单号
*/
private long orderId;
/**
* 订单金额
*/
private double amount;
/**
* 有参构造器
* @param orderId
* @param amount
*/
public Order (long orderId, double amount) {
this.orderId = orderId;
this.amount = amount;
}
public long getOrderId() {
return orderId;
}
public void setOrderId(long orderId) {
this.orderId = orderId;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
@Override
public String toString() {
return "Order{" +
"orderId=" + orderId +
", amount=" + amount +
'}';
}
/**
* 订单发货方法
*/
@Override
public void delivery() {
System.out.printf("订单号%s,金额%s,已发货!", orderId, amount);
}
}
interface 接口 Deliverable
package com.test.ioc.xml;
public interface Deliverable {
/**
* 发货
*/
void delivery();
}
2、spring-chapter2.xml
在spring-chapter2.xml文件中通过bean标签将User类交给IoC容器管理。具体配置如下:
<?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">
<!--Order有参构造器-->
<bean id="order" class="com.test.ioc.xml.Order">
<constructor-arg index="0" value="202001141004"/>
<constructor-arg index="1" value="8888"/>
</bean>
</beans>
*.xml 有三种方式编写
<!-- 第一种根据index参数下标设置 -->
<bean id="order" class="com.test.ioc.xml.Order">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="202001141004"/>
<constructor-arg index="1" value="8888"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="order" class="com.test.ioc.xml.Order">
<!-- name指参数名 -->
<constructor-arg name="orderId" value="202001141004"/>
<constructor-arg name="amount" value="8888"/>
</bean>
<!-- 第三种根据参数类型设置 -->
<bean id="order" class="com.test.ioc.xml.Order>
<constructor-arg type="java.lang.Long" value="202001141004"/>
<constructor-arg type="java.lang.Double" value="8888"/> </bean>
3、测试类 OrderTest.java
在单元测试类OrderTest中,通过依赖注入得到Deliverable的对象Order,单元测试代码如下:
package ioc.xml;
import com.test.ioc.xml.Deliverable;
import com.test.ioc.xml.Speakable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* 测试XML方式的IoC
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-chapter2.xml")
public class XmlTest {
//Spring 容器注入依赖的Speakable对象
@Autowired
private Speakable speakable;
//Spring 容器注入依赖的Deliverable对象
@Autowired
private Deliverable deliverable;
@Test
public void test() {
speakable.say();
deliverable.delivery();
}
}
其中@RunWith这个注解指定了让单元测试运行于Spring的环境中,@ContextConfiguration这个注解指定Spring加载的配置文件。
4、测试结果
执行单元测试,测试结果如下。
D:\Environments\jdk-11.0.2\bin\java.exe...
订单号202001141004,金额8888.0,已发货!
Order{orderId=202001141004, amount=8888.0}
Process finished with exit code 0
结论:在配置文件加载的时候。其中管理的对象都已经初始化了!
Order使用有参构造器的方式,实现有参构造器的IoC。
通过注解方式实现
除了通过构造器实现IoC,还可以通过Spring提供的注解方法实现IoC,这也是企业开发过程中最常用的一种IoC实现方式。
1、编写一个Student实体类
下面通过学生类Student阐述注解的方式实现IoC。
接口 HomeWork.java
package com.test.ioc.annotation;
public interface HomeWork {
/**
* 写家庭作业
*/
void doHomeWork();
}
Student类的定义如下:
package com.test.ioc.annotation;
import org.springframework.stereotype.Service;
@Service
public class Student implements HomeWork {
/**
* 写家庭作业
*/
@Override
public void doHomeWork() {
System.out.println("我是学生,我要写家庭作业");
}
}
注意此时的Student类上加了一个@Service注解,这告诉Spring,让其管理这个类的对象,因此开发人员就不再需要管理Student对象了。
2、编写我们的spring文件
与XML方式实现的IoC不同的是,注解方式除了配置@Service注解外,还需要指定Spring对需要管理的bean目录,否则Spring不能定位其需要管理的bean。具体配置如下:
<!--spring 管理的bean的路径-->
<context:component-scan base-package="com.test.ioc"></context:component-scan>
spring-chapter2.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">
<!--spring 管理的bean的路径-->
<context:component-scan base-package="com.test.ioc"></context:component-scan>
</beans>
3、依赖注入,将对象注入到测试类中
接下来在测试类AnnotationTest中通过依赖注入,将HomeWork对象注入到AnnotationTest测试类中,测试代码如下:
package ioc.annotation;
import com.test.ioc.annotation.HomeWork;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 测试注解方式的IoC
*/
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:spring-chapter2.xml")
public class AnnotationTest {
@Autowired
private HomeWork homeWork;
//Spring 容器注入依赖的Deliverable对象
@Test
public void test() {
homeWork.doHomeWork();
}
}
4、测试结果
运行单元测试,测试结果如下:
D:\Environments\jdk-11.0.2\bin\java.exe
我是学生,我要写家庭作业
Process finished with exit code 0
除了例中的注解@Service可以实现Bean的IoC以外,Spring还提供了很多其他的注解来实现IoC。
(1)@Component将Java类标记成一个Spring Bean组件。
(2)@Service将业务层实现类标记成一个Spring Bean组件。
(3)@Controller将控制层类标记成一个Spring Bean组件。
(4)@Repository将一个持久层实现类标记成一个Spring Bean组件。
Spring 配置
别名
alias 设置别名 , 为bean设置别名 , 可以设置多个别名
<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="user" alias="userNew"/>
Bean配置
<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
import
团队的合作通过import来实现 .
<import resource="{path}/beans.xml"/>
参考资料
1.Spring 5企业级开发实战/周冠亚,黄文毅著.—北京:清华大学出版社,2019
2.Spring:概述、IOC理论-秦疆-–https://www.bilibili.com/video/av71110355
3.Spring:第一个程序、对象创建方式、配置说明-秦疆。https://www.bilibili.com/video/av71110355