二、Spring IOC控制反转

1:IOC推导

》传统业务调用编程

定义一个userDao接口:UserDao

  1. package com.spring;
  2. public interface UserDao {
  3. public void getUser();
  4. }

定义一个userDao接口实现类(基于mysql):UserMysqlDaoImpl

  1. package com.spring;
  2. public class UserMysqlDaoImpl implements UserDao{
  3. @Override
  4. public void getUser() {
  5. System.out.println("调用了Mysql数据驱动");
  6. }
  7. }

定义一个userDao接口实现类(基于oracle):UserOracleDaoImpl

  1. package com.spring;
  2. public class UserOracleDaoImpl implements UserDao{
  3. @Override
  4. public void getUser() {
  5. System.out.println("调用了oracle数据驱动");
  6. }
  7. }

定义一个UserService接口:UserService

  1. package com.spring;
  2. public interface UserService {
  3. public void getUser();
  4. }

定义一个UserService接口实现类:UserServiceImpl

  1. package com.spring;
  2. public class UserServiceImpl implements UserService{
  3. UserDao userDao = new UserMysqlDaoImpl();//mysql实现
  4. //UserDao userDao = new UserOracleDaoImpl();//oracle实现
  5. @Override
  6. public void getUser() {
  7. userDao.getUser();
  8. }
  9. }

编写测试类:

  1. public static void main(String[] args) {
  2. UserService userService = new UserServiceImpl();
  3. userService.getUser();
  4. }

解释:

1:如果我们要在UserServiceImpl 调用userDao的业务实现,必须要new 一个对象

2:如果我们要修改UserServiceImpl 调用userDao的业务实现,必须要重新new一个对象

3:以上两点让代码紧耦合,而且对代码的管理增加了难度,要不停的修改代码

》IOC 编码式业务调用编程

基于传统业务调用编程的UserDao 、UserMysqlDaoImpl 、UserOracleDaoImpl、UserService

修改UserService接口实现类:UserServiceImpl

  1. package com.spring;
  2. public class UserServiceImpl implements UserService{
  3. private UserDao userDao;//定义要调用的接口变量
  4. //给这个变量增加set方法(重点)
  5. public void setUserDao(UserDao userDao) {
  6. this.userDao = userDao;
  7. }
  8. @Override
  9. public void getUser() {
  10. userDao.getUser();
  11. }
  12. }

编写测试类:

  1. public static void main(String[] args) {
  2. UserService userService = new UserServiceImpl();
  3. //通过set方法注入不同的业务实现
  4. ((UserServiceImpl) userService).setUserDao(new UserOracleDaoImpl());
  5. userService.getUser();
  6. }

》IOC 配置式业务调用编程

基于IOC 编码式业务调用编程的UserDao 、UserMysqlDaoImpl 、UserOracleDaoImpl、UserService、UserServiceImpl

在resources类目录下创建spring配置文件beans.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <!--mysql业务实现-->
  6. <bean id="userMysqlDao" class="com.spring.UserMysqlDaoImpl"></bean>
  7. <!--oracle业务实现-->
  8. <bean id="userOracleDao" class="com.spring.UserOracleDaoImpl"></bean>
  9. <!--ref:引用spring创建好的对象-->
  10. <bean id="userService" class="com.spring.UserServiceImpl">
  11. <property name="userDao" ref="userOracleDao"></property>
  12. </bean>
  13. </beans>

编写测试类:

  1. public static void main(String[] args) {
  2. //获取spring容器
  3. ApplicationContext applicationContext =
  4. new ClassPathXmlApplicationContext("beans.xml");
  5. //通过id获取bean
  6. UserServiceImpl userService =
  7. (UserServiceImpl) applicationContext.getBean("userService");
  8. //调用
  9. userService.getUser();
  10. }

2:Spring开始

1:Spring初识

定义一个VO对象:UserVo

  1. package com.spring.Vo;
  2. public class UserVo {
  3. private String userName;//用户名
  4. private String userPass;//密码
  5. public String getUserName() {
  6. return userName;
  7. }
  8. public void setUserName(String userName) {
  9. this.userName = userName;
  10. }
  11. public String getUserPass() {
  12. return userPass;
  13. }
  14. public void setUserPass(String userPass) {
  15. this.userPass = userPass;
  16. }
  17. }

通过spring容器实例化UserVo对象:

  1. <!--
  2. 使用spring来创建对象 在spring中称之为bean
  3. UserVo userVo = new UserVo()
  4. id = 变量名
  5. class = new UserVo()
  6. name = 属性值
  7. value = 属性赋值
  8. -->
  9. <bean id="userVo" class="com.spring.Vo.UserVo">
  10. <property name="userName" value="admin"></property>
  11. <property name="userPass" value="123456"></property>
  12. </bean>

编写测试类:

  1. public static void main(String[] args) {
  2. //获取容器
  3. ApplicationContext applicationContext =
  4. new ClassPathXmlApplicationContext("beans.xml");
  5. //获取bean
  6. UserVo userVo = (UserVo) applicationContext.getBean("userVo");
  7. System.out.println(userVo.getUserName()+userVo.getUserPass());
  8. }

2:构造器

spring实例化bean是基于无参构造方法的,如果加入了有参构造方法,那么set方法就不起作用了,而且bean也会报错(&除非再加一个无参构造器,这样set和构造器实例化bean都可以使用&)!

在UserVo中加入有参构造方法:

  1. public UserVo(String userName, String userPass) {
  2. this.userName = userName;
  3. this.userPass = userPass;
  4. }

sping实例化bean:

  1. <bean id="userVo" class="com.spring.Vo.UserVo">
  2. <constructor-arg index="0" value="admin"></constructor-arg>
  3. <constructor-arg index="1" value="123"></constructor-arg>
  4. </bean>

或者

  1. <bean id="userVo" class="com.spring.Vo.UserVo">
  2. <constructor-arg name="userName" value="admin"></constructor-arg>
  3. <constructor-arg name="userPass" value="123456"></constructor-arg>
  4. </bean>

3:spring简单配置

1:alias:别名

  1. <!--
  2. 给userVo 起一个别名为myUser
  3. 既可以通过userVo获取到这个bean
  4. 也可以通过myUser获取到这个bean
  5. -->
  6. <alias name="userVo" alias="myUser"></alias>

2:bean:实例化对象

  1. <!--
  2. id:bean的唯一标识,相当于类中的变量名
  3. class:bean所对应的的全限定名 包名 + 类名
  4. name:别名 可以定义多个,也可以得到bean对象
  5. -->
  6. <bean id="userVo" class="com.spring.Vo.UserVo" name="u1,u2">
  7. <property name="userName" value="admin"></property>
  8. <property name="userPass" value="12345"></property>
  9. </bean>

3:import:合并配置文件

  1. <!--将多个Spring配置文件合并为一个,用于多人开发-->
  2. <import resource="beans.xml"></import>

4:依赖注入 DI

依赖:就是spring创建bean; 注入:就是给bean的属性赋值

一、构造器注入(上面已经讲过.......略)

二、Set注入(重点)

可以通过Set接口注入普通类型、对象类型、数组类型、集合类型、map类型、set类型、null类型、Properties类型。

1:定义一个Address Javabean对象(添加get和set以及tostring方法)

  1. package com.spring.Vo;
  2. public class Address {
  3. private String address;
  4. }

2:定义一个StudentJavabean对象(添加get和set以及tostring方法)

  1. package com.spring.Vo;
  2. import java.util.*;
  3. public class Student {
  4. private String name; //普通类型
  5. private Address address; //对象类型
  6. private String[] books; //数组类型
  7. private List<String> hobbys; //集合类型
  8. private Map<String,String> card; //map类型
  9. private Set<String> games;//set类型
  10. private String wife; //null类型
  11. private Properties info; //Properties类型
  12. }

3:创建spring配置文件

  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 http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <!--实例化Address类-->
  6. <bean id="address" class="com.spring.Vo.Address">
  7. <property name="address" value="北京"></property>
  8. </bean>
  9. <!--实例化Student类-->
  10. <bean id="student" class="com.spring.Vo.Student">
  11. <!--第一 普通注入:value-->
  12. <property name="name" value="张三"></property>
  13. <!--第二 bean注入:ref-->
  14. <property name="address" ref="address"></property>
  15. <!--第三 数组注入:array-->
  16. <property name="books">
  17. <array>
  18. <value>语文</value>
  19. <value>数学</value>
  20. <value>英语</value>
  21. </array>
  22. </property>
  23. <!--第四 list集合注入:list-->
  24. <property name="hobbys">
  25. <list>
  26. <value>听歌</value>
  27. <value>看书</value>
  28. <value>跑步</value>
  29. </list>
  30. </property>
  31. <!--第五 map集合注入:map-->
  32. <property name="card">
  33. <map>
  34. <entry key="k1" value="v1"></entry>
  35. <entry key="k2" value="v2"></entry>
  36. </map>
  37. </property>
  38. <!--第六 set集合注入:set-->
  39. <property name="games">
  40. <set>
  41. <value>CS</value>
  42. <value>LoL</value>
  43. </set>
  44. </property>
  45. <!--第七 null集合注入:null-->
  46. <property name="wife">
  47. <null />
  48. </property>
  49. <!--第八 Properties集合注入:props-->
  50. <property name="info">
  51. <props>
  52. <prop key="number" >10001</prop>
  53. <prop key="age">18</prop>
  54. </props>
  55. </property>
  56. </bean>
  57. </beans>

4:编写测试

  1. //获取容器
  2. ApplicationContext applicationContext =
  3. new ClassPathXmlApplicationContext("applicationContext.xml");
  4. //获取bean
  5. Student student = (Student) applicationContext.getBean("student");
  6. System.out.println(student.toString());

5:查看打印结果

  1. Student
  2. {
  3. name='张三',
  4. address=Address{address='北京'},
  5. books=[语文, 数学, 英语],
  6. hobbys=[听歌, 看书, 跑步],
  7. card={k1=v1, k2=v2},
  8. games=[CS, LoL],
  9. wife='null',
  10. info={age=18, number=10001}
  11. }

三、命名空间注入

p命名空间:针对set注入方式

c命名空间:针对构造器注入方式

  1. xmlns:p="http://www.springframework.org/schema/p"
  2. xmlns:c="http://www.springframework.org/schema/c"

1:定义一个UserInfo Javabean对象

  1. package com.spring.Vo;
  2. public class UserInfo {
  3. private String name;
  4. private String age;
  5. public void setName(String name) {
  6. this.name = name;
  7. }
  8. public void setAge(String age) {
  9. this.age = age;
  10. }
  11. /*无参构造器*/
  12. public UserInfo() {
  13. }
  14. /*有参构造器*/
  15. public UserInfo(String name, String age) {
  16. this.name = name;
  17. this.age = age;
  18. }
  19. @Override
  20. public String toString() {
  21. return "UserInfo{" +
  22. "name='" + name + '\'' +
  23. ", age='" + age + '\'' +
  24. '}';
  25. }
  26. }

2:创建spring配置文件

  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. xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:c="http://www.springframework.org/schema/c"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  7. <!--p命名空间:必须有无参构造方法-->
  8. <bean id="userInfo" class="com.spring.Vo.UserInfo" p:name="admin" p:age="18"></bean>
  9. <!--c命名空间:必须有有参构造方法-->
  10. <bean id="userInfo2" class="com.spring.Vo.UserInfo" c:name="zhangsan" c:age="15"></bean>
  11. </beans>

4:编写测试

  1. @Test
  2. public void test01(){
  3. //获取容器
  4. ApplicationContext applicationContext =
  5. new ClassPathXmlApplicationContext("applicationContext.xml");
  6. //获取bean(试试userInfo)
  7. UserInfo userInfo =applicationContext.getBean("userInfo2", UserInfo.class);
  8. System.out.println(userInfo.toString());
  9. }

四、bean的作用域

1:单例模式(singleton):每次从容器中拿到的对象都是同一个,spring默认值

  1. <bean id="userInfo" class="com.spring.Vo.UserInfo" scope="singleton"></bean>
  1. //获取容器
  2. ApplicationContext applicationContext =
  3. new ClassPathXmlApplicationContext("applicationContext.xml");
  4. //获取bean
  5. UserInfo userInfo01 =applicationContext.getBean("userInfo", UserInfo.class);
  6. UserInfo userInfo02 =applicationContext.getBean("userInfo", UserInfo.class);
  7. System.out.println(userInfo01 == userInfo02);
  8. /*结果:true */

2:原型模式(prototype):每次从容器中拿到的对象都是新的

  1. <bean id="userInfo" class="com.spring.Vo.UserInfo" scope="prototype"></bean>
  1. //获取容器
  2. ApplicationContext applicationContext =
  3. new ClassPathXmlApplicationContext("applicationContext.xml");
  4. //获取bean
  5. UserInfo userInfo01 =applicationContext.getBean("userInfo", UserInfo.class);
  6. UserInfo userInfo02 =applicationContext.getBean("userInfo", UserInfo.class);
  7. System.out.println(userInfo01 == userInfo02);
  8. /*结果:false*/

3:其他模式:request、sessoin、application;只能在web开发中使用

五、bean的自动装配

spring会在上下文中自动寻找,并自动给bean装配属性

在spring中有三种装配方式:

1:在xml总显示的配置

2:隐式的自动装配

3:在java中显示装配

场景:一个人拥有两只宠物

创建三个对象:Dog、Cat、People

  1. package com.spring.vo1;
  2. public class Dog {
  3. /*模拟狗叫*/
  4. public void shout(){
  5. System.out.println("wangwang~~~");
  6. }
  7. }
  1. package com.spring.vo1;
  2. public class Cat {
  3. /*模拟猫叫*/
  4. public void shout(){
  5. System.out.println("miaomiao~~~~");
  6. }
  7. }
  1. package com.spring.vo1;
  2. public class People {
  3. private Dog dog;/*宠物狗*/
  4. private Cat cat;/*宠物猫*/
  5. private String name;/*人的姓名*/
  6. public Dog getDog() {
  7. return dog;
  8. }
  9. public void setDog(Dog dog) {
  10. this.dog = dog;
  11. }
  12. public Cat getCat() {
  13. return cat;
  14. }
  15. public void setCat(Cat cat) {
  16. this.cat = cat;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. }

spring实例化三个对象:

  1. <bean id="cat" class="com.spring.vo1.Cat"></bean>
  2. <bean id="dog" class="com.spring.vo1.Dog"></bean>
  3. <bean id="people" class="com.spring.vo1.People">
  4. <property name="name" value="king"></property>
  5. <property name="cat" ref="cat"></property>
  6. <property name="dog" ref="dog"></property>
  7. </bean>

测试:

  1. //获取容器
  2. ApplicationContext applicationContext =
  3. new ClassPathXmlApplicationContext("applicationContext.xml");
  4. //获取bean
  5. People people =applicationContext.getBean("people", People.class);
  6. people.getCat().shout();
  7. people.getDog().shout();

输出结果:

  1. miaomiao~~~~
  2. wangwang~~~

把以上场景改为自动装配:autowire

1:byName:自动在上下文中找 和自己对象中定义的属性名对应的bean id(id必须全局唯一)

  1. <bean id="cat" class="com.spring.vo1.Cat"></bean>
  2. <bean id="dog" class="com.spring.vo1.Dog"></bean>
  3. <!--byName:会自动在上下文中找 和自己对象中定义的属性名对应的bean id-->
  4. <bean id="people" class="com.spring.vo1.People" autowire="byName">
  5. <property name="name" value="king"></property>
  6. </bean>

2:byType:自动在上下文中找 和自己对象中定义的属性名的类型对应的bean(class必须全局唯一)

  1. <bean id="cat" class="com.spring.vo1.Cat"></bean>
  2. <bean id="dog" class="com.spring.vo1.Dog"></bean>
  3. <!--byType:会自动在上下文中找 和自己对象中定义的属性名的类型对应的bean-->
  4. <bean id="people" class="com.spring.vo1.People" autowire="byType">
  5. <property name="name" value="king"></property>
  6. </bean>

Spring5:控制反转的更多相关文章

  1. 憋了很久,终于弄懂什么是IOC(控制反转)

    导航 共享充电宝 IOC思想 复杂的依赖关系 IOC定义 Spring中的IOC IOC与工厂模式 IOC容器的技术剖析 结语 参考   本节是摘自<Spring Boot 实战纪实>的第 ...

  2. .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用

    再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...

  3. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

  4. 控制反转、依赖注入、Unity容器

    控制反转原则 依赖注入 Install-Package Unity:https://www.nuget.org/packages/Unity/ Github:https://github.com/un ...

  5. 控制反转(IOC)

    对于很多大中型项目为了实现解耦都用到了控制反转. 常用的控制反转有unity,autoface,spring.Net 使用它们的目的归根结底就一个:避免了直接new一个对象. 今天抽时间将三种控制反转 ...

  6. 回顾Spirng ioc 控制反转

    Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的.结合网上对Spring Ioc的理解,回顾一下自 ...

  7. 小菜学习设计模式(五)—控制反转(Ioc)

    写在前面 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Metho ...

  8. 谈谈php里的IOC控制反转,DI依赖注入

    理论 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和"DI依赖注入"是什么,能够解决什么问题,这些在维基百科中有非常清晰的说明. 控制反转(In ...

  9. Java之控制反转和依赖注入

    1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public clas ...

随机推荐

  1. python之道15

    请实现一个装饰器,限制该函数被调用的频率,如10秒一次(借助于time模块,time.time())(面试题,有点难度,可先做其他) 答案 # 思路 运行不能用 import time def wra ...

  2. iOS 性能优化收集

    iOS 性能调试 instrument Instrument Instrument之Core Animation工具 避免图层混合 ①.确保控件的opaque属性设置为true,确保backgroun ...

  3. Centos7 中打开和关闭防火墙及端口

    1.firewalld的基本使用 启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status f ...

  4. [vijos1883]月光的魔法<递归>

    题目链接:https://vijos.org/p/1883 这道题还有另外一种版本叫天神下凡,属于模拟题,可是模拟题数据太水以至于模拟题A了都不一定在vijos上A.... 在模拟题里我用的是一种类似 ...

  5. NodeMCU入坑指南-低成本打造零舍友闻风丧胆WiFi断网神器

    前言 最近对IoT方面比较感兴趣,所以在某宝上入手了一块NodeMCU的开发板,至于为什么我选择这块开发板呢?嘿嘿,当然是因为便宜啊

  6. Spring Boot创建一个HelloWorld项目

    目录 Spring Boot 简介 微服务框架 以前使用spring开发web的方式 Spring Boot 启动器介绍 如何创建一个helloword的SpringBoot项目 Spring Boo ...

  7. #VScodd集成Git Bash 命令行 #怎么把Git Bash集成到VScode

    配置 Step1. File-Preferences-Setting Step2. 搜索"terminal>integrated>shell A" Step3. 找到t ...

  8. 《Three.js 入门指南》2.4.1- 照相机 - 透视投影demo

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 一夜搞懂 | JVM 线程安全与锁优化

    前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习内存模型与线程? 之前我们学习了内存模型和线程,了解了 JMM 和线程,初步 ...

  10. 1012 The Best Rank (25 分)

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...