二、Spring IOC控制反转

1:IOC推导

》传统业务调用编程

定义一个userDao接口:UserDao

package com.spring;

public interface UserDao {

    public void getUser();
}

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

package com.spring;

public class UserMysqlDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("调用了Mysql数据驱动");
}
}

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

package com.spring;

public class UserOracleDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("调用了oracle数据驱动");
}
}

定义一个UserService接口:UserService

package com.spring;

public interface UserService {
public void getUser();
}

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

package com.spring;

public class UserServiceImpl implements UserService{

    UserDao userDao = new UserMysqlDaoImpl();//mysql实现
//UserDao userDao = new UserOracleDaoImpl();//oracle实现 @Override
public void getUser() {
userDao.getUser();
}
}

编写测试类:

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

解释:

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

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

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

》IOC 编码式业务调用编程

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

修改UserService接口实现类:UserServiceImpl

package com.spring;

public class UserServiceImpl implements UserService{

    private UserDao userDao;//定义要调用的接口变量

    //给这个变量增加set方法(重点)
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
} @Override
public void getUser() {
userDao.getUser();
}
}

编写测试类:

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

》IOC 配置式业务调用编程

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

在resources类目录下创建spring配置文件beans.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"> <!--mysql业务实现-->
<bean id="userMysqlDao" class="com.spring.UserMysqlDaoImpl"></bean>
<!--oracle业务实现-->
<bean id="userOracleDao" class="com.spring.UserOracleDaoImpl"></bean> <!--ref:引用spring创建好的对象-->
<bean id="userService" class="com.spring.UserServiceImpl">
<property name="userDao" ref="userOracleDao"></property>
</bean>
</beans>

编写测试类:

public static void main(String[] args) {
//获取spring容器
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("beans.xml");
//通过id获取bean
UserServiceImpl userService =
(UserServiceImpl) applicationContext.getBean("userService"); //调用
userService.getUser(); }

2:Spring开始

1:Spring初识

定义一个VO对象:UserVo

package com.spring.Vo;

public class UserVo {

    private String userName;//用户名

    private String userPass;//密码

    public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public String getUserPass() {
return userPass;
} public void setUserPass(String userPass) {
this.userPass = userPass;
}
}

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

<!--
使用spring来创建对象 在spring中称之为bean
UserVo userVo = new UserVo()
id = 变量名
class = new UserVo()
name = 属性值
value = 属性赋值
-->
<bean id="userVo" class="com.spring.Vo.UserVo">
<property name="userName" value="admin"></property>
<property name="userPass" value="123456"></property>
</bean>

编写测试类:

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

2:构造器

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

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

public UserVo(String userName, String userPass) {
this.userName = userName;
this.userPass = userPass;
}

sping实例化bean:

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

或者

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

3:spring简单配置

1:alias:别名

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

2:bean:实例化对象

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

3:import:合并配置文件

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

4:依赖注入 DI

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

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

二、Set注入(重点)

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

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

package com.spring.Vo;

public class Address {
private String address;
}

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

package com.spring.Vo;

import java.util.*;

public class Student {

    private String name; //普通类型
private Address address; //对象类型
private String[] books; //数组类型
private List<String> hobbys; //集合类型
private Map<String,String> card; //map类型
private Set<String> games;//set类型
private String wife; //null类型
private Properties info; //Properties类型
}

3:创建spring配置文件

<?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"> <!--实例化Address类-->
<bean id="address" class="com.spring.Vo.Address">
<property name="address" value="北京"></property>
</bean> <!--实例化Student类-->
<bean id="student" class="com.spring.Vo.Student">
<!--第一 普通注入:value-->
<property name="name" value="张三"></property> <!--第二 bean注入:ref-->
<property name="address" ref="address"></property> <!--第三 数组注入:array-->
<property name="books">
<array>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</array>
</property> <!--第四 list集合注入:list-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>看书</value>
<value>跑步</value> </list>
</property> <!--第五 map集合注入:map-->
<property name="card">
<map>
<entry key="k1" value="v1"></entry>
<entry key="k2" value="v2"></entry>
</map>
</property> <!--第六 set集合注入:set-->
<property name="games">
<set>
<value>CS</value>
<value>LoL</value>
</set>
</property> <!--第七 null集合注入:null-->
<property name="wife">
<null />
</property> <!--第八 Properties集合注入:props-->
<property name="info">
<props>
<prop key="number" >10001</prop>
<prop key="age">18</prop>
</props>
</property> </bean>
</beans>

4:编写测试

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

5:查看打印结果

      Student
{
name='张三',
address=Address{address='北京'},
books=[语文, 数学, 英语],
hobbys=[听歌, 看书, 跑步],
card={k1=v1, k2=v2},
games=[CS, LoL],
wife='null',
info={age=18, number=10001}
}

三、命名空间注入

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

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

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

1:定义一个UserInfo Javabean对象

package com.spring.Vo;

public class UserInfo {

    private String name;
private String age; public void setName(String name) {
this.name = name;
} public void setAge(String age) {
this.age = age;
} /*无参构造器*/
public UserInfo() {
} /*有参构造器*/
public UserInfo(String name, String age) {
this.name = name;
this.age = age;
} @Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}

2:创建spring配置文件

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

4:编写测试

@Test
public void test01(){
//获取容器
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean(试试userInfo)
UserInfo userInfo =applicationContext.getBean("userInfo2", UserInfo.class); System.out.println(userInfo.toString());
}

四、bean的作用域

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

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

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

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

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

五、bean的自动装配

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

在spring中有三种装配方式:

1:在xml总显示的配置

2:隐式的自动装配

3:在java中显示装配

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

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

package com.spring.vo1;

public class Dog {

    /*模拟狗叫*/
public void shout(){
System.out.println("wangwang~~~");
}
}
package com.spring.vo1;

public class Cat {

    /*模拟猫叫*/
public void shout(){
System.out.println("miaomiao~~~~");
}
}
package com.spring.vo1;

public class People {

    private Dog dog;/*宠物狗*/
private Cat cat;/*宠物猫*/
private String name;/*人的姓名*/ public Dog getDog() {
return dog;
} public void setDog(Dog dog) {
this.dog = dog;
} public Cat getCat() {
return cat;
} public void setCat(Cat cat) {
this.cat = cat;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

spring实例化三个对象:

<bean id="cat" class="com.spring.vo1.Cat"></bean>

<bean id="dog" class="com.spring.vo1.Dog"></bean>

<bean id="people" class="com.spring.vo1.People">
<property name="name" value="king"></property>
<property name="cat" ref="cat"></property>
<property name="dog" ref="dog"></property>
</bean>

测试:

//获取容器
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean
People people =applicationContext.getBean("people", People.class); people.getCat().shout();
people.getDog().shout();

输出结果:

miaomiao~~~~
wangwang~~~

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

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

<bean id="cat" class="com.spring.vo1.Cat"></bean>

<bean id="dog" class="com.spring.vo1.Dog"></bean>

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

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

<bean id="cat" class="com.spring.vo1.Cat"></bean>

<bean id="dog" class="com.spring.vo1.Dog"></bean>

<!--byType:会自动在上下文中找 和自己对象中定义的属性名的类型对应的bean-->
<bean id="people" class="com.spring.vo1.People" autowire="byType">
<property name="name" value="king"></property>
</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. matplotlib命令与格式:参数配置文件与参数配置

    转自 https://my.oschina.net/swuly302/blog/94805 自定义matplotlib Created Saturday 08 December 2012 5.1 ma ...

  2. Node.js安装过程

    今天电脑的node用不了了,于是决定重新安装一下 一.安装Node.js 1.首先,可以直接去Node的官网寻找适合自己电脑系统的版本 官网地址:https://nodejs.org/en/downl ...

  3. 1.NET Core 概述

    .NET Core 概述 .NET Core是一个免费的.开源的.跨平台的.广泛使用的Web框架:它是由微软维护的.社区广泛参与支持的一个框架..NET Core可以运行在:Windows.MacOS ...

  4. Python第十一章-常用的核心模块01-collections模块

    python 自称 "Batteries included"(自带电池, 自备干粮?), 就是因为他提供了很多内置的模块, 使用这些模块无需安装和配置即可使用. 本章主要介绍 py ...

  5. 高并发解决方案限流技术-----使用RateLimiter实现令牌桶限流

    1,RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率.通常可应用于抢购限流防止冲垮系统:限制某接口.服务单位 ...

  6. Python python 五种数据类型--数字

    一:Number 数字 不可变类型 整型(Int) - 通常被称为是整型或整数,是正或负整数,不带小数点. 长整型(long integers) - 无限大小的整数,整数最后是一个大写或小写的L.(P ...

  7. 添加属于自己的python模块空间

    在我们学习python的过程中会遇到很多时候,我们需要自己曾经写过的模块,它可能是一个函数或者其他的东西,,,, 下面是我的解决过程,如果你像将自己建立的文件夹当作你存放自己写的模块的地方,你需要将你 ...

  8. Linux下使用FastDFS

    本文所有操作均在CentOS 7.x环境下进行. 1.1.单节点FastDFS 整个安装过程非常复杂,很容易出错,建议进行多次备份. 我们这里不打算安装多台虚拟机,因此会把tracker和storag ...

  9. element的多文件上传

    项目需求: 可上传多个文件 可删除 文件过大时用户输入可上传至其他网站,并将文件名和地址上传至本网站 问题点: 大文件用户输入内容无法合并到已上传文件的列表进行展示 上传多个大文件地址时前面已上传的大 ...

  10. 如何将 .NetFramework WebApi 按业务拆分成多个模块

    在 .NetFramework 中使用 WebApi ,在不讨论 微服务 的模式下,大部分都是以层来拆分库的 : 基础设施 数据存储层 服务层 WeApi 层 一些其它的功能库 项目结构可能会像下面这 ...