简单记录 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 , 他会自动下载对应的依赖项 .

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-webmvc</artifactId>
  4. <version>5.2.22.RELEASE</version>
  5. </dependency>

https://repo.spring.io/release/org/springframework/spring/

创建一个空白maven项目实现IoC。

XML方式实现

XML方式实现用构造器方式实现IoC分为无参构造器和有参构造器两种。

通过无参构造方法来创建

User使用无参构造器的方式,实现无参构造器的IoC。

1、编写一个User实体类

User类的实现如下:

User.java

  1. package com.test.ioc.xml;
  2. /**
  3. * 无参构造器实现IoC
  4. */
  5. public class User {
  6. /**
  7. * 姓名
  8. */
  9. private String name;
  10. /**
  11. * 无参构造器
  12. */
  13. public User () {
  14. System.out.println("user无参构造方法");
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. @Override
  23. public String toString() {
  24. return "User{" +
  25. "name='" + name + '\'' +
  26. '}';
  27. }
  28. /**
  29. * 显示姓名
  30. */
  31. public void showName(){
  32. System.out.println("我叫 " + name +",哈哈!");
  33. }
  34. /**
  35. * 说话的方法
  36. */
  37. public void say() {
  38. System.out.println("大家好!");
  39. }
  40. }

2、编写我们的spring文件

编写我们的spring文件 , 这里我们命名为spring-chapter2.xml

在resources下spring-chapter2.xml文件中,通过bean标签将User类交给IoC容器管理,代码如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--bean就是java对象 , 由Spring创建和管理-->
  7. <!-- User无参构造器 -->
  8. <bean id="user" class="com.test.ioc.xml.User">
  9. <property name="name" value="柳小子"/>
  10. </bean>
  11. </beans>

3、测试类 UserTest.java

我们可以去进行测试了,哈哈

UserTest.java

  1. package ioc.xml;
  2. import com.test.ioc.xml.User;
  3. import org.junit.Test;
  4. import org.springframework.context.ApplicationContext;
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;
  6. /**
  7. * @author Liu Awen Email:willowawen@gmail.com
  8. * @create 2020-01-14 9:47 AM
  9. */
  10. public class UserTest {
  11. @Test
  12. public void test(){
  13. //解析beans.xml文件 , 生成管理相应的Bean对象
  14. ApplicationContext context = new ClassPathXmlApplicationContext("spring-chapter2.xml");
  15. //getBean : 参数即为spring配置文件中bean的id .
  16. User user = (User) context.getBean("user");
  17. user.say();
  18. user.showName();
  19. }
  20. }

4、测试结果

  1. D:\Environments\jdk-11.0.2\bin\java.exe...
  2. user无参构造方法
  3. 大家好!
  4. 我叫 柳小子,哈哈!
  5. 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类的定义如下:

  1. package com.test.ioc.xml;
  2. /**
  3. * 有参构造器实现IoC
  4. */
  5. public class Order implements Deliverable {
  6. /**
  7. * 订单号
  8. */
  9. private long orderId;
  10. /**
  11. * 订单金额
  12. */
  13. private double amount;
  14. /**
  15. * 有参构造器
  16. * @param orderId
  17. * @param amount
  18. */
  19. public Order (long orderId, double amount) {
  20. this.orderId = orderId;
  21. this.amount = amount;
  22. }
  23. public long getOrderId() {
  24. return orderId;
  25. }
  26. public void setOrderId(long orderId) {
  27. this.orderId = orderId;
  28. }
  29. public double getAmount() {
  30. return amount;
  31. }
  32. public void setAmount(double amount) {
  33. this.amount = amount;
  34. }
  35. @Override
  36. public String toString() {
  37. return "Order{" +
  38. "orderId=" + orderId +
  39. ", amount=" + amount +
  40. '}';
  41. }
  42. /**
  43. * 订单发货方法
  44. */
  45. @Override
  46. public void delivery() {
  47. System.out.printf("订单号%s,金额%s,已发货!", orderId, amount);
  48. }
  49. }

interface 接口 Deliverable

  1. package com.test.ioc.xml;
  2. public interface Deliverable {
  3. /**
  4. * 发货
  5. */
  6. void delivery();
  7. }

2、spring-chapter2.xml

在spring-chapter2.xml文件中通过bean标签将User类交给IoC容器管理。具体配置如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--Order有参构造器-->
  7. <bean id="order" class="com.test.ioc.xml.Order">
  8. <constructor-arg index="0" value="202001141004"/>
  9. <constructor-arg index="1" value="8888"/>
  10. </bean>
  11. </beans>

*.xml 有三种方式编写

  1. <!-- 第一种根据index参数下标设置 -->
  2. <bean id="order" class="com.test.ioc.xml.Order">
  3. <!-- index指构造方法 , 下标从0开始 -->
  4. <constructor-arg index="0" value="202001141004"/>
  5. <constructor-arg index="1" value="8888"/>
  6. </bean>
  1. <!-- 第二种根据参数名字设置 -->
  2. <bean id="order" class="com.test.ioc.xml.Order">
  3. <!-- name指参数名 -->
  4. <constructor-arg name="orderId" value="202001141004"/>
  5. <constructor-arg name="amount" value="8888"/>
  6. </bean>
  1. <!-- 第三种根据参数类型设置 -->
  2. <bean id="order" class="com.test.ioc.xml.Order>
  3. <constructor-arg type="java.lang.Long" value="202001141004"/>
  4. <constructor-arg type="java.lang.Double" value="8888"/> </bean>

3、测试类 OrderTest.java

在单元测试类OrderTest中,通过依赖注入得到Deliverable的对象Order,单元测试代码如下:

  1. package ioc.xml;
  2. import com.test.ioc.xml.Deliverable;
  3. import com.test.ioc.xml.Speakable;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.test.context.ContextConfiguration;
  8. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  9. /**
  10. * 测试XML方式的IoC
  11. */
  12. @RunWith(SpringJUnit4ClassRunner.class)
  13. @ContextConfiguration("classpath:spring-chapter2.xml")
  14. public class XmlTest {
  15. //Spring 容器注入依赖的Speakable对象
  16. @Autowired
  17. private Speakable speakable;
  18. //Spring 容器注入依赖的Deliverable对象
  19. @Autowired
  20. private Deliverable deliverable;
  21. @Test
  22. public void test() {
  23. speakable.say();
  24. deliverable.delivery();
  25. }
  26. }

其中@RunWith这个注解指定了让单元测试运行于Spring的环境中,@ContextConfiguration这个注解指定Spring加载的配置文件。

4、测试结果

执行单元测试,测试结果如下。

  1. D:\Environments\jdk-11.0.2\bin\java.exe...
  2. 订单号202001141004,金额8888.0,已发货!
  3. Order{orderId=202001141004, amount=8888.0}
  4. Process finished with exit code 0

结论:在配置文件加载的时候。其中管理的对象都已经初始化了!

Order使用有参构造器的方式,实现有参构造器的IoC。

通过注解方式实现

除了通过构造器实现IoC,还可以通过Spring提供的注解方法实现IoC,这也是企业开发过程中最常用的一种IoC实现方式。

1、编写一个Student实体类

下面通过学生类Student阐述注解的方式实现IoC。

接口 HomeWork.java

  1. package com.test.ioc.annotation;
  2. public interface HomeWork {
  3. /**
  4. * 写家庭作业
  5. */
  6. void doHomeWork();
  7. }

Student类的定义如下:

  1. package com.test.ioc.annotation;
  2. import org.springframework.stereotype.Service;
  3. @Service
  4. public class Student implements HomeWork {
  5. /**
  6. * 写家庭作业
  7. */
  8. @Override
  9. public void doHomeWork() {
  10. System.out.println("我是学生,我要写家庭作业");
  11. }
  12. }

注意此时的Student类上加了一个@Service注解,这告诉Spring,让其管理这个类的对象,因此开发人员就不再需要管理Student对象了。

2、编写我们的spring文件

与XML方式实现的IoC不同的是,注解方式除了配置@Service注解外,还需要指定Spring对需要管理的bean目录,否则Spring不能定位其需要管理的bean。具体配置如下:

  1. <!--spring 管理的bean的路径-->
  2. <context:component-scan base-package="com.test.ioc"></context:component-scan>

spring-chapter2.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--spring 管理的bean的路径-->
  7. <context:component-scan base-package="com.test.ioc"></context:component-scan>
  8. </beans>

3、依赖注入,将对象注入到测试类中

接下来在测试类AnnotationTest中通过依赖注入,将HomeWork对象注入到AnnotationTest测试类中,测试代码如下:

  1. package ioc.annotation;
  2. import com.test.ioc.annotation.HomeWork;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.test.context.ContextConfiguration;
  7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. /**
  10. * 测试注解方式的IoC
  11. */
  12. @RunWith(SpringRunner.class)
  13. @ContextConfiguration("classpath:spring-chapter2.xml")
  14. public class AnnotationTest {
  15. @Autowired
  16. private HomeWork homeWork;
  17. //Spring 容器注入依赖的Deliverable对象
  18. @Test
  19. public void test() {
  20. homeWork.doHomeWork();
  21. }
  22. }

4、测试结果

运行单元测试,测试结果如下:

  1. D:\Environments\jdk-11.0.2\bin\java.exe
  2. 我是学生,我要写家庭作业
  3. 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设置别名 , 可以设置多个别名

  1. <!--设置别名:在获取Bean的时候可以使用别名获取-->
  2. <alias name="user" alias="userNew"/>

Bean配置

  1. <!--bean就是java对象,由Spring创建和管理-->
  2. <!--
  3. id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
  4. 如果配置id,又配置了name,那么name是别名
  5. name可以设置多个别名,可以用逗号,分号,空格隔开
  6. 如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
  7. class是bean的全限定名=包名+类名
  8. -->
  9. <bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
  10. <property name="name" value="Spring"/>
  11. </bean>

import

团队的合作通过import来实现 .

  1. <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

【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC的更多相关文章

  1. Spring配置文件中bean标签中init-method和destroy-method和用注解方式配置

    Person类: public class Person {       private int i = 0;          public Person(){           System.o ...

  2. 【初识Spring】对象(Bean)实例化及属性注入(注解方式)

    通过xml的方式进行对象的实列化或属性注入或许有一些繁琐,所以在开发中常用的方式更多是通过注解的方式实现对象实例化和属性注入的. 开始之前 1.导入相关的包(除了导入基本的包还要导入aop的包): 创 ...

  3. 【spring boot】14.spring boot集成mybatis,注解方式OR映射文件方式AND pagehelper分页插件【Mybatis】pagehelper分页插件分页查询无效解决方法

    spring boot集成mybatis,集成使用mybatis拖沓了好久,今天终于可以补起来了. 本篇源码中,同时使用了Spring data JPA 和 Mybatis两种方式. 在使用的过程中一 ...

  4. spring与hibernate整合配置基于Annotation注解方式管理实务

    1.配置数据源 数据库连接基本信息存放到properties文件中,因此先加载properties文件 <!-- jdbc连接信息 --> <context:property-pla ...

  5. Spring MVC 数据验证——validate注解方式

    1.说明 学习注解方式之前,应该先学习一下编码方式的spring注入.这样便于理解验证框架的工作原理.在出错的时候,也能更好的解决这个问题.所以本次博客教程也是基于编码方式.仅仅是在原来的基础加上注解 ...

  6. 【核心核心】4.Spring【IOC】注解方式

    1.导入jar包 2.创建对应的类 public interface HelloService { public void sayHello(); } /** * @Component(value=& ...

  7. 从零开始学JAVA(09)-使用SpringMVC4 + Mybatis + MySql 例子(注解方式开发)

    项目需要,继续学习springmvc,这里加入Mybatis对数据库的访问,并写下一个简单的例子便于以后学习,希望对看的人有帮助.上一篇被移出博客主页,这一篇努力排版整齐,更原创,希望不要再被移出主页 ...

  8. SpringMVC注解方式与文件上传

    目录: springmvc的注解方式 文件上传(上传图片,并显示) 一.注解 在类前面加上@Controller 表示该类是一个控制器在方法handleRequest 前面加上 @RequestMap ...

  9. SpringMVC 注解方式进行配置页面跳转

    @ 目录 修改IndexController 修改springmvc-servlet.xml 效果 修改IndexController 在类前面加上@Controller 表示该类是一个控制器 在方法 ...

  10. hibernate annotation注解方式来处理映射关系

    在hibernate中,通常配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于annotation的注解方式,熟话说,萝卜青菜,可有所爱,每个人都有自己喜欢的配置方式,我在试了这两种方式 ...

随机推荐

  1. uniapp导入导出Excel

    众所周知,uniapp作为跨端利器,有诸多限制,其中之一便是vue页面不支持传统网页的dom.bom.blob等对象. 所以,百度上那些所谓的导入导出excel的方法,大部分都用不了,比如xlsx那个 ...

  2. 【UnitTest】使用方法

    UnitTest安装 pip install unittest 详细教程: https://www.cnblogs.com/yufeihlf/p/5707929.html断言:  DDT数据驱动: c ...

  3. oracle DG查看延时时间

    oracle DG查看延时时间 SQL> select value from v$dataguard_stats where name='apply lag'; 例如: SQL> sele ...

  4. 自动化管理平台rundeck的安装方法

    简介 RunDeck 是用 Java/Grails 写的开源工具,帮助用户在数据中心或者云环境中自动化各种操作和流程.通过命令行或者web界面,用户可以对任意数量的服务器进行操作,大大降低了对服务器自 ...

  5. vue单页面应用刷新网页后vuex的state数据丢失的解决办法

    第一种方案 首先将数据保存在vuex的store中,同时将这些信息也保存在sessionStorage中.这里需要注意的是vuex中的变量是响应式的,而sessionStorage不是,当你改变vue ...

  6. Greenplum 性能优化之路 --(一)分区表

    一.什么是分区表 分区表就是将一个大表在物理上分割成若干小表,并且整个过程对用户是透明的,也就是用户的所有操作仍然是作用在大表上,不需要关心数据实际上落在哪张小表里面.Greenplum 中分区表的原 ...

  7. 简单的冒泡排序算法(java)

    package lianxi; public class BubbleSort { public static void main(String[] args) { int[] array = {12 ...

  8. 为什么游戏公司的server不愿意微服务化?

    背景介绍 笔者最近去面试了家游戏公司(有上市).我问他,公司有没有做微服务架构的打算及考量?他很惊讶的,我没听说过微服务耶,你可以解释一下吗? 我大概说了,方便测试,方便维护,方便升级,服务之间松耦合 ...

  9. java判断路径是文件夹还是文件

    当给定一个路径没有后缀的时候,很难分辨代码是文件还是文件夹,如下图: 我在桌面建立了一个名为one的文件,路径为:/Users/XXXXXX/Desktop/one java代码如下: import ...

  10. Git全栈开发者使用指南

    一.Git基础 1.Git简介 Git是一种分布式版本控制系统,由Linux之父Linus开发. 所谓分布式版本管理系统,就是在每一台机器上都有一个完整的仓库. 2.Git官网 Git官网:git 在 ...