Spring——Spring IOC(1)

Spring IOC

创建工程:
在这里插入图片描述

1.程序的耦合

  • 耦合:耦合指的就是对象之间的依赖关系。对象之间的耦合越高,维护成本越高。

  • 案例:没有引入IOC容器时系统的Web层、业务层、持久层存在耦合

    /*** 持久层实现类*/
    public class UserDaoImpl implements UserDao {@Overridepublic void addUser(){System.out.println("insert into tb_user......");}
    }
    
    /*** 业务层实现类*/
    public class UserServiceImpl implements UserService {//硬编码:此处有依赖关系private UserDao userDao = new UserDaoImpl();public void addUser(){userDao.addUser();}
    }
    
    /*** 模拟表现层*/
    public class Client {public static void main(String[] args) {//硬编码:此处有依赖关系UserService userService = new UserServiceImpl();userService.addUser();}
    }
    
  • 问题分析:

    上边的代码service层在依赖dao层的实现类,此时如果更改dao了层的实现类或此时没有dao层实现类,编译将不能通过。

  • IOC(工厂模式)解耦:

    1. 把所有的dao和service对象使用配置文件配置起来
    2. 当服务器启动时读取配置文件
    3. 把这些对象通过反射创建出来并保存在容器中
    4. 在使用的时候,直接从工厂拿

2.工程模式的IOC解决程序耦合

2.1 什么是IOC

  • IOC (Inverse of Control)即控制反转:正转是自己创建依赖对象;反转是有IOC工厂来创建依赖对象;

  • 原来:

    ​ 我们在获取对象时,都是采用new的方式。是主动的。

  • 现在:

​ 我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。

​ 这种被动接收的方式获取对象的思想就是控制反转,它是spring框架的核心之一。

2.2 工厂模式的IOC解耦合

  • 案例一

    /*** bean工厂*/
    public class BeanFactory_v1 {/*** 获得UserServiceImpl对象* @return*/public static UserService getUserService(){return new UserServiceImpl();}/*** 获得UserDaoImpl对象* @return*/public static UserDao getUserDao(){return new UserDaoImpl();}
    }
    

    问题:我们在开发中会有很多个service和dao,此时工厂类就要添加无数个方法。

  • 案例二

    #1、配置要使用的dao和service
    UserDao=com.wt.dao.UserDaoImpl
    UserService=com.wt.service.UserServiceImpl
    
    /*** bean工厂*/
    public class BeanFactory_v2 {private static Properties prop = new Properties();/*** 根据全类名获取bean对象* @param beanName* @return* @throws ClassNotFoundException*/public static Object getBean(String beanName) {try {//不能使用:web工程发布后没有src目录//InputStream is = new FileInputStream("src/bean.properties");InputStream is = BeanFactory_v2.class.getClassLoader().getResourceAsStream("bean.properties");prop.load(is);return Class.forName(prop.getProperty(beanName)).newInstance();} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] args) {System.out.println(prop.get("UserService"));System.out.println(getBean("UserService"));}
    }
    
    /*** 业务层实现类*/
    public class UserServiceImpl implements UserService {private UserDao userDao = (UserDao) BeanFactory.getBean("UserDao");public void addUser(){userDao.addUser();}
    }
    

    测试:

    /*** 模拟表现层*/
    public class Client {public static void main(String[] args) {//直接引用接口实现类for (int i = 0; i < 5; i++) {UserService userService = (UserService)BeanFactory.getBean("UserService");System.out.println(userService);}}
    }
    

    问题:

    1. 每次都会创建新的对象
    2. 程序运行时才创建对象(读取配置文件)
  • 案例三

    package com.wt.factory;import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set;/*** bean工厂*/
    public class BeanFactory_v3 {//定义一个容器,用于存放对象private static Map<String, Object> beans = new HashMap<>();/*** 加载配置文件*/static {try {//2、读取配置文件//不能使用:web工程发布后没有src目录//InputStream is = new FileInputStream("src/bean.properties");InputStream is = BeanFactory_v3.class.getClassLoader().getResourceAsStream("bean.properties");//3、通过反射创建对象,把对象存到容器中Properties prop = new Properties();prop.load(is);Set<Map.Entry<Object, Object>> entrySet = prop.entrySet();for (Map.Entry<Object, Object> entry : entrySet) {String key = entry.getKey().toString();String beanName = entry.getValue().toString();Object value = Class.forName(beanName).newInstance();beans.put(key, value);}} catch (Exception e) {e.printStackTrace();}}/*** 4、在使用的时候,直接从工厂拿* @param beanName* @return*/public static Object getBean(String beanName) {try {return beans.get(beanName);} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] args) {System.out.println(getBean("UserService"));}
    }
    

3 Spring的IOC解决程序耦合

3.1 创建工程

3.1.1 pom.xml
<?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>com.wt</groupId><artifactId>Spring_IOC_Xml</artifactId><version>1.0-SNAPSHOT</version><properties><!-- 项目源码及编译输出的编码 --><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 项目编译JDK版本 --><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!-- Spring常用依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.8.RELEASE</version></dependency></dependencies>
</project>

注意:Jar包彼此存在依赖,只需引入最外层Jar即可由Maven自动将相关依赖Jar引入到项目中。

Spring常用功能的Jar包依赖关系

​ 核心容器由 beans、core、context 和 expression(Spring Expression Language,SpEL)4个模块组成。

  • spring-beans和spring-core模块是Spring框架的核心模块,包含了控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)。BeanFactory使用控制反转对应用程序的配置和依赖性规范与实际的应用程序代码进行了分离。BeanFactory属于延时加载,也就是说在实例化容器对象后并不会自动实例化Bean,只有当Bean被使用时,BeanFactory才会对该 Bean 进行实例化与依赖关系的装配。
  • spring-context模块构架于核心模块之上,扩展了BeanFactory,为它添加了Bean生命周期控制、框架事件体系及资源加载透明化等功能。此外,该模块还提供了许多企业级支持,如邮件访问、远程访问、任务调度等,ApplicationContext 是该模块的核心接口,它的超类是 BeanFactory。与BeanFactory不同,ApplicationContext实例化后会自动对所有的单实例Bean进行实例化与依赖关系的装配,使之处于待用状态。
  • spring-expression 模块是统一表达式语言(EL)的扩展模块,可以查询、管理运行中的对象,同时也可以方便地调用对象方法,以及操作数组、集合等。它的语法类似于传统EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数。EL的特性是基于Spring产品的需求而设计的,可以非常方便地同Spring IoC进行交互。
3.1.2 dao
/*** 持久层实现类*/
public class UserDaoImpl implements UserDao {@Overridepublic void addUser(){System.out.println("insert into tb_user......");}
}
3.1.3 service
/*** 业务层实现类*/
public class UserServiceImpl implements UserService {//此处有依赖关系private UserDao userDao = new UserDaoImpl();@Overridepublic void addUser(){userDao.addUser();}
}

3.2 IOC

3.2.1 applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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"><!--2、把对象交给spring来创建id:给对象在容器中提供一个唯一标识。用于获取对象	class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数--><bean id="userDao" class="com.wt.dao.UserDaoImpl"></bean><bean id="userService" class="com.wt.service.UserServiceImpl"></bean>
</beans>

注意:命名无限制,约定俗成命名有:spring-context.xml、applicationContext.xml、beans.xml

3.2.2 测试
/*** 模拟表现层*/
public class Client {public static void main(String[] args) {//1.使用ApplicationContext接口,就是在获取spring容器ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");//2.根据bean的id获取对象UserDao userDao = (UserDao) ac.getBean("userDao");System.out.println(userDao);UserService userService = (UserService) ac.getBean("userService");System.out.println(userService);userService.addUser();}
}
  • 问题:service层仍然耦合

3.3 DI

概述:DI(Dependency Injection)依赖注入,在Spring创建对象的同时,为其属性赋值,称之为依赖注入。

3.3.1 构造函数注入

顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置的方式,让spring框架来为我们注入。具体代码如下:

/*** 业务层实现类*/
public class UserServiceImpl implements UserService {private UserDao userDao;private String name;private Integer age;public UserServiceImpl(UserDao userDao, String name, Integer age) {this.userDao = userDao;this.name = name;this.age = age;}public void addUser(){System.out.println(name+","+age);userDao.addUser();}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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"><!--2、把对象交给spring来创建--><bean id="userDao" class="com.wt.dao.UserDaoImpl"></bean><bean id="userService" class="com.wt.service.UserServiceImpl"><!--要求:类中需要提供一个对应参数列表的构造函数。标签:constructor-arg==给谁赋值:==index:指定参数在构造函数参数列表的索引位置name:指定参数在构造函数中的名称==赋什么值:==value:它能赋的值是基本数据类型和String类型ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean--><constructor-arg name="userDao" ref="userDao"></constructor-arg><constructor-arg name="name" value="张三"></constructor-arg><constructor-arg name="age" value="18"></constructor-arg></bean>
</beans>
3.3.2 set方法注入

顾名思义,就是在类中提供需要注入成员的set方法。具体代码如下:

/*** 业务层实现类*/
public class UserServiceImpl implements UserService {private UserDao userDao;private String name;private Integer age;public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}public void addUser(){System.out.println(name+","+age);userDao.addUser();}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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"><!--2、把对象交给spring来创建--><bean id="userDao" class="com.wt.dao.UserDaoImpl"></bean><bean id="userService" class="com.wt.service.UserServiceImpl"><!--要求:property标签:constructor-arg==给谁赋值:==name:找的是类中set方法后面的部分==赋什么值:==value:它能赋的值是基本数据类型和String类型ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean--><property name="userDao" ref="userDao"></property><property name="name" value="张三"></property><property name="age" value="18"></property></bean>
</beans>
3.3.3 自动注入

不用在配置中 指定为哪个属性赋值,由spring自动根据某个 “原则” ,在工厂中查找一个bean并为属性注入值。具体代码如下:

/*** 业务层实现类*/
public class UserServiceImpl implements UserService {private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void addUser(){userDao.addUser();}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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"><!--2、把对象交给spring来创建--><bean id="userDao" class="com.wt.dao.UserDaoImpl"></bean><!--autowire="byType":按照类型自动注入值--><bean id="userService" class="com.wt.service.UserServiceImpl" autowire="byType"></bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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"><!--2、把对象交给spring来创建--><bean id="userDao" class="com.wt.dao.UserDaoImpl"></bean><!--autowire="byType":按照类型自动注入值--><bean id="userService" class="com.wt.service.UserServiceImpl" autowire="byName"></bean>
</beans>
3.3.4 注入集合类型的属性

顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。我们这里介绍注入数组,List,Set,Map。具体代码如下:

/*** 业务层实现类*/
public class UserServiceImpl implements UserService {private UserDao userDao;private String[] myStrs;private List<String> myList;private Set<String> mySet;private Map<String,String> myMap;public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void setMyStrs(String[] myStrs) {this.myStrs = myStrs;}public void setMyList(List<String> myList) {this.myList = myList;}public void setMySet(Set<String> mySet) {this.mySet = mySet;}public void setMyMap(Map<String, String> myMap) {this.myMap = myMap;}public void addUser(){System.out.println(Arrays.toString(myStrs));System.out.println(myList);System.out.println(mySet);System.out.println(myMap);userDao.addUser();}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入schema约束-->
<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"><!--2、把对象交给spring来创建--><bean id="userDao" class="com.wt.dao.UserDaoImpl"></bean><bean id="userService" class="com.wt.service.UserServiceImpl"><!--要求:property标签:constructor-arg==给谁赋值:==name:找的是类中set方法后面的部分==赋什么值:==value:它能赋的值是基本数据类型和String类型ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean--><property name="userDao" ref="userDao"></property><!-- 给mySet集合注入数据 --><property name="mySet"><set><value>AAA</value><value>BBB</value><value>CCC</value></set></property><!-- 注入array数组数据 --><property name="myArray"><array><value>AAA</value><value>BBB</value><value>CCC</value></array></property><!-- 注入list集合数据 --><property name="myList"><list><value>AAA</value><value>BBB</value><value>CCC</value></list></property><!-- 注入Map数据 --><property name="myMap"><map><entry key="testA" value="aaa"></entry><entry key="testB" value="bbb"></entry></map></property></bean>
</beans>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/596604.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot的测试

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;…

12.递归汉诺塔

使用递归实现汉诺塔 public class Main {public static void move(char pos1,char pos2) {System.out.print(pos1" > "pos2" ");}public static void han(int n,char pos1,char pos2,char pos3) {if(n 1) {move(pos1,pos3);return ;}han(n-1,pos1,pos…

阿里、字节等大厂系统测试方法的知识点总结,终于被我搞到手了

系统测试一般采取黑盒测试&#xff0c;系统测试的方法也比较多&#xff0c;其中常用的方法有&#xff1a;多任务测试、临界测试、中断测试、等价划分测试 多任务测试 多任务测试是指在非idle状态下&#xff0c;测试对象处于工作状态时&#xff0c;有新的事件发生&#xff0c;…

multipath 内核接口及框架介绍

文章目录 1 云主机使用网络存储 io 流程2 multipath 介绍 1 云主机使用网络存储 io 流程 对于一个云服务环境&#xff0c;大致会有网络节点&#xff0c;存储节点&#xff0c;计算节点&#xff0c;控制节点&#xff0c;其中虚拟云主机在计算节点工作&#xff0c;而虚拟云主机&a…

LCR 176. 判断是否为平衡二叉树

解题思路&#xff1a; class Solution {public boolean isBalanced(TreeNode root) {return recur(root) ! -1;}private int recur(TreeNode root) {if (root null) return 0;int left recur(root.left);if(left -1) return -1;int right recur(root.right);if(right -1) …

ebay头像如何设置?eBay店铺的头像怎么改?-站斧浏览器

ebay头像如何设置&#xff1f; eBay店铺的头像可以通过以下方式进行设置&#xff1a; 登录eBay账户&#xff1a;店主需要使用自己的eBay账号登录到eBay网站。 进入店铺管理后台&#xff1a;在登录后&#xff0c;店主可以点击页面右上角的用户名或店铺名称&#xff0c;从下拉…

被低估的流量宝地,如何通过Reddit为Shopify店铺引流?

独立站店铺相对于电商平台来说&#xff0c;有一个运营难点那就是需要自主引流。做好引流&#xff0c;你的Shopify店铺也就成功了一半。Reddit作为国外知名的论坛平台&#xff0c;非常适合作为引流的阵地&#xff0c;许多人对这个网站尚不了解&#xff0c;接下来就为大家介绍如何…

HackTheBox - Medium - Linux - Socket

Socket Socket 是一台中等难度的 Linux 机器&#xff0c;其特点是反转 Linux/Windows 桌面应用程序以获取其源代码&#xff0c;从那里发现其 Web 套接字服务中的“SQL”注入。转储数据库会显示一个哈希值&#xff0c;一旦破解&#xff0c;就会产生对该框的“SSH”访问。最后&a…

1295. X的因子链(数论/求1~N的所以质因子)

题目&#xff1a; 1295. X的因子链 - AcWing题库 输入样例&#xff1a; 2 3 4 10 100输出样例&#xff1a; 1 1 1 1 2 1 2 2 4 6 思路&#xff1a; 代码&#xff1a; #include <cstdio> #include <cstring> #include <iostream> #include <algorithm…

Gin 路由注册与请求参数获取

Gin 路由注册与请求参数获取 文章目录 Gin 路由注册与请求参数获取一、Web应用开发的两种模式1.前后端不分离模式2.前后端分离模式 二、RESTful介绍三、API接口3.1 RESTful API设计指南3.2 API与用户的通信协议3.3 RestFul API接口设计规范3.3.1 api接口3.3.2 接口文档&#xf…

viewer插件——预览图片时一直闪烁——问题修复,亲测有效

viewer插件——预览图片时一直闪烁——问题修复&#xff0c;亲测有效 viewer插件的介绍遇到的问题——图片会一直重复加载&#xff0c;造成图片在闪烁的效果解决方法 viewer插件的介绍 之前写过一篇文章&#xff0c;是关于v-viewer图片预览插件——vue2插件集合(elementUi中的…

JAVA 终极面试题

目录标题 一: JAVA 基础1.JDK和JRE有什么区别&#xff1f;2. 面向对象的特征&#xff08;了解&#xff09;3. 和equals的区别是什么&#xff1f;4.两个对象的hashCode()相同,则equals()一定为true&#xff0c;对吗&#xff1f;5.final关键字在java中的作用6.java中的Math.round…

bat批处理文件_命令汇总(1)

文章目录 1、复制文件&#xff1a;2、 移动文件&#xff1a;3、删除文件&#xff1a;4、创建目录&#xff1a;5、删除目录&#xff1a;6、切换目录&#xff1a;7、显示当前目录&#xff1a;8、运行程序&#xff1a;9、显示系统环境变量&#xff1a;10、设置环境变量&#xff1a…

HCIA-Datacom题库(自己整理分类的)——OSPF协议判断

1.路由表中某条路由信息的Proto为OSPF则此路由的优先级一定为10。√ 2.如果网络管理员没有配置骨干区域,则路由器会自动创建骨干区域&#xff1f; 路由表中某条路由信息的Proto为OSPF&#xff0c;则此路由的优先级一定为10。 当两台OSPF路由器形成2-WAY邻居关系时&#xff0…

Android 相机库CameraView源码解析 (四) : 带滤镜预览

1. 前言 这段时间&#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位&#xff0c;在项目前期&#xff0c;的确为我们节省了不少时间。 但随着项目持续深入&#xff0c;对于CameraView的使用进入深水区&#xff0c;逐…

【OpenBMC】的内部README 模板

OpenBMC 本项目的AST2500分支核心代码的机型是ast2500-default&#xff0c;克隆代码后进入编译环境的命令为&#xff1a; source setup ast2500-default 一、源码下载、配置以及编译 重要&#xff1a;请参阅confluence 详细步骤 二、代码使用方法 目前所有自定义修改的代码…

Node.js 文件写入详解:最佳实践与示例

文件写入是 Node.js 中的一项重要任务&#xff0c;它允许你将数据保存到本地文件系统中&#xff0c;供后续使用。这个功能在许多应用中都有广泛的应用&#xff0c;包括数据备份、日志记录、配置文件更新等。在本文&#xff0c;我们将介绍如何在 Node.js 中执行文件写入操作&…

【C#】知识点实践序列之UrlEncode在线URL网址编码、解码

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是2024年第8篇文章&#xff0c;此篇文章是C#知识点实践序列文章&#xff0c; 博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 地址编码大家应该比较经常遇到和使用到&…

CAN数据记录仪在新能源车上的应用

随着新能源汽车的快速发展&#xff0c;对车辆安全和性能的要求也越来越高。在新能源车中&#xff0c;液位传感器是必不可少的零部件之一&#xff0c;用于监测电池液位、冷却液位等关键参数。在测试阶段需要工作人员花费大量时间跟车去获取它的CAN数据&#xff0c;从而分析是否有…

在 Linux 中开启 Flask 项目持续运行

在 Linux 中开启 Flask 项目持续运行 在部署 Flask 项目时&#xff0c;情况往往并不是那么理想。默认情况下&#xff0c;关闭 SSH 终端后&#xff0c;Flask 服务就停止了。这时&#xff0c;您需要找到一种方法在 Linux 服务器上实现持续运行 Flask 项目&#xff0c;并在服务器…