Spring IOC详解 我就是我 2024-03-22 15:30 22阅读 0赞 ### 章节内容 ### * Spring IOC技术实现 * Spring IOC设值注入 * Spring IOC构造注入 ### 章节目标 ### * 掌握Spring IOC技术实现 * 掌握Spring IOC设置注入 * 掌握Spring IOC构造注入 ### 第一节 Spring简介 ### #### 1. Spring 简介 #### Spring 是目前主流的 Java 开发框架,是 Java 世界最为成功的框架。其目的是用于简化企业级应用程序开发的难度和周期,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。 什么是框架? 框架是一个半成品,提供了基本的运行功能,但具体业务实现需要我们去编写。 #### 2. Spring体系结构 #### ![72ebd55397834d5599e943dfee3c3f33.png][] EL = Expression Language 表达式语言 SpEL = Spring Expression Language Spring表达式语言 2.1 Data Access/Integration Data Access/Integration表示数据访问/集成层,包含了JDBC、ORM、OXM、JMS、Transactions模块。 > **JDBC 模块** > > 提供了一个 JBDC 的样例模板,使用这些模板能消除传统冗长的 JDBC 编码还有必须的事务控制,而且能享受到 Spring 管理事务的好处。 > **ORM 模块** > > 提供与流行的“对象-关系”映射框架无缝集成的 API,包括 JPA、JDO、Hibernate 和 MyBatis 等。而且还可以使用 Spring 事务管理,无需额外控制事务。 > **OXM 模块** > > 提供了一个支持 Object /XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。将 Java 对象映射成 XML 数据,或者将XML 数据映射成 Java 对象。 > **JMS 模块** > > 指 Java 消息服务,提供一套 “消息生产者、消息消费者”模板用于更加简单的使用 JMS,JMS 用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。 > **Transactions 事务模块** > > 支持编程和声明式事务管理。 2.2 Web Spring 的 Web 层包括 Web、Servlet、WebSocket 和 Portlet 组件。 > **Web 模块** > > 提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IOC 容器初始化以及 Web 应用上下文。 > **Servlet 模块** > > 提供了一个 Spring MVC Web 框架实现。Spring MVC 框架提供了基于注解的请求资源注入、更简单的数据绑定、数据验证等及一套非常易用的 JSP 标签,完全无缝与 Spring 其他技术协作。 > **WebSocket 模块** > > 提供了简单的接口,用户只要实现响应的接口就可以快速的搭建 WebSocket Server,从而实现双向通讯。 > **Portlet 模块** > > 提供了在 Portlet 环境中使用 MVC 实现,类似 Web-Servlet 模块的功能。 2.3 Core Container Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 SpEL 表达式语言模块组成,没有这些核心容器,也不可能有 AOP、Web 等上层的功能。 > **Beans 模块** > > 提供了框架的基础部分,包括控制反转和依赖注入。 > **Core 核心模块** > > 封装了 Spring 框架的底层部分,包括资源访问、类型转换及一些常用工具类。 > **Context 上下文模块** > > 建立在 Core 和 Beans 模块的基础之上,集成 Beans 模块功能并添加资源绑定、数据验证、国际化、Java EE 支持、容器生命周期、事件传播等。ApplicationContext 接口是上下文模块的焦点。 > **SpEL 模块** > > 提供了强大的表达式语言支持,支持访问和修改属性值,方法调用,支持访问及修改数组、容器和索引器,命名变量,支持算数和逻辑运算,支持从 Spring 容器获取 Bean,它也支持列表投影、选择和一般的列表聚合等。 2.4 AOP、Aspects、Instrumentation和Messaging 在 Core Container 之上是 AOP、Aspects 等模块。 > **AOP 模块** > > 提供了面向切面编程实现,提供比如日志记录、权限控制、性能统计等通用功能和业务逻辑分离的技术,并且能动态的把这些功能添加到需要的代码中,这样各司其职,降低业务逻辑和通用功能的耦合。 > **Aspects 模块** > > 提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。 > **Instrumentation 模块** > > 提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。 > **messaging 模块** > > Spring 4.0 以后新增了消息(Spring-messaging)模块,该模块提供了对消息传递体系结构和协议的支持。 2.5 Test模块 > **Test 模块** > > Spring 支持 Junit 和 TestNG 测试框架,而且还额外提供了一些基于 Spring 的测试功能,比如在测试 Web 框架时,模拟 Http 请求的功能。 ### 第二节 Spring IOC ### #### 1. IOC 概念 #### IOC全称为 Inverse Of Control,表示控制反转。指的是程序员使用硬编码创建的对象转为由Spring容器来创建,对于对象生命周期的控制交给Spring容器来管理。控制反转解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健 #### 2. 如何使用 IOC #### 2.1 依赖包引入 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.11</version> </dependency> 2.3 创建类 public class User { } 2.2 编写配置文件 <?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标签表示一个对象--> <bean name="user" class="com.qf.spring.ioc.model.User" /> </beans> 2.4 编写测试案例 public class BeanTest { @Test public void getIocTest(){ //应用上下文使用的是类路径下XML文档作为当前应用上下文 ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); //从上下文中根据bean的名称或者ID获取bean对象 User user = context.getBean("user", User.class); System.out.println(user); } } #### 3. DI概念 #### DI全称为Dependency Injection,表示依赖注入。指的是在Spring创建对象的同时,为其属性赋值 #### 4. 如何使用 DI #### 4.1 在类中添加属性 @Data public class User { private String username; private String password; } 4.2 修改配置文件 <?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标签表示一个对象--> <bean name="user" class="com.qf.spring.ioc.model.User"> <!--为对象的属性注入值:这里name属性的值必须与set方法保持一致--> <property name="username" value="admin" /> <property name="password" value="123456" /> </bean> </beans> 4.3 再次测试 #### 5. 注入方式 #### 5.1 设值注入 设值注入指的是通过set方法为属性注入值。设值注入必须保证存在无参构造,否则将报错。 @Data public class Student { private String name; private String sex; private int age; private Date birthday; } <!--application.xml--> <bean name="stu" class="com.qf.spring.ioc.model.Student"> <property name="name" value="张三" /> <property name="age" value="20" /> <property name="sex" value="男" /> <!--这里需要注意:日期类型的默认格式yyyy/MM/dd--> <property name="birthday" value="2021/10/10" /> </bean> @Test public void studentTest(){ //应用上下文使用的是类路径下XML文档作为当前应用上下文 ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); //从上下文中根据bean的名称或者ID获取bean对象 Student stu = context.getBean("stu", Student.class); System.out.println(stu); } 5.2 构造注入 构造注入指的是通过构造放入为属性注入值。 @Data @AllArgsConstructor @NoArgsConstructor public class Student { private String name; private String sex; private int age; private Date birthday; } <!--application.xml--> <bean name="s" class="com.qf.spring.ioc.model.Student"> <!--这里按照顺序为属性注入值--> <constructor-arg index="0" value="李四" /> <constructor-arg index="1" value="女" /> <constructor-arg index="2" value="22" /> <constructor-arg index="3" value="2020/05/05" /> </bean> @Test public void studentConstructorTest(){ //应用上下文使用的是类路径下XML文档作为当前应用上下文 ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); //从上下文中根据bean的名称或者ID获取bean对象 Student stu = context.getBean("s", Student.class); System.out.println(stu); } #### 6. 注入类型 #### 6.1 注入常用数据类型 常用数据类型指8种基本数据类型以及对应的包装类、日期类型、字符串等。 6.2 注入引用数据类型 对于引用数据类型,spring 提供了两种注入值的方式。一种是通过 ref 属性来引用 bean 对象进行值的注入,一种是通过 bean 标签来创建一个 bean 对象进行值的注入。 <property name="" ref="" /> <property name=""> <bean class=""></bean> </property> @Data public class User { private String username; private String password; private UserInfo userInfo; } @Data public class UserInfo { private int id; private String name; private String sex; private int age; } <bean id="info" class="com.qf.spring.ioc.model.UserInfo"> <property name="id" value="1" /> <property name="name" value="张三" /> <property name="sex" value="男" /> <property name="age" value="20" /> </bean> <!--bean标签表示一个对象--> <bean name="user" class="com.qf.spring.ioc.model.User"> <!--为对象的属性注入值:这里name属性的值必须与set方法保持一致--> <property name="username" value="admin" /> <property name="password" value="123456" /> <!--引用id为info的bean对象进行值的注入--> <property name="userInfo" ref="info" /> </bean> <bean name="u" class="com.qf.spring.ioc.model.User"> <!--为对象的属性注入值:这里name属性的值必须与set方法保持一致--> <property name="username" value="admin" /> <property name="password" value="123456" /> <property name="userInfo"> <!--使用bean标签创建一个bean对象进行值的注入--> <bean class="com.qf.spring.ioc.model.UserInfo"> <property name="id" value="2" /> <property name="name" value="李四" /> <property name="sex" value="女" /> <property name="age" value="22" /> </bean> </property> </bean> 6.3 注入数组 spring 提供了 array 标签来进行数组类型的属性值的注入。 @Data public class Clazz { private int id; private String name; private Student[] students; } <bean name="clazz" class="com.qf.spring.ioc.model.Clazz"> <property name="id" value="1" /> <property name="name" value="张三" /> <property name="students"> <array> <!--引用数据类型 可以使用bean标签创建bean对象注入值--> <!--<bean class=""></bean>--> <!--引用数据类型 可以使用ref标签引用bean对象注入值--> <ref bean="s" /> <ref bean="stu" /> <!--常用数据类型 可以使用value标签直接注入值--> <!-- <value></value>--> </array> </property> </bean> 6.4 注入集合 6.4.1 List集合 @Data @AllArgsConstructor @NoArgsConstructor public class Student { private String name; private String sex; private int age; private Date birthday; private List<Double> scores; } <bean name="stu" class="com.qf.spring.ioc.model.Student"> <property name="name" value="张三" /> <property name="age" value="20" /> <property name="sex" value="男" /> <!--这里需要注意:日期类型的默认格式yyyy/MM/dd--> <property name="birthday" value="2021/10/10" /> <property name="scores"> <list> <value>80.0</value> <value>90.0</value> <value>81.0</value> <value>82.0</value> </list> </property> </bean> <bean name="s" class="com.qf.spring.ioc.model.Student"> <!--这里按照顺序为属性注入值--> <constructor-arg index="0" value="李四" /> <constructor-arg index="1" value="女" /> <constructor-arg index="2" value="22" /> <constructor-arg index="3" value="2020/05/05" /> <constructor-arg index="4"> <list> <value>80.0</value> <value>90.0</value> <value>81.0</value> <value>82.0</value> </list> </constructor-arg> </bean> 6.4.2 Set集合 @Data public class Person { private String name; private Set<String> friendNames; } <bean name="p" class="com.qf.spring.ioc.model.Person"> <property name="name" value="李刚" /> <property name="friendNames"> <set> <value>李四</value> <value>王五</value> </set> </property> </bean> 6.4.3 注入Map @Data public class Person { private String name; private List<String> friendNames; private Map<String, Object> map; } <bean name="p" class="com.qf.spring.ioc.model.Person"> <property name="name" value="李刚" /> <property name="friendNames"> <set> <value>李四</value> <value>王五</value> </set> </property> <property name="map"> <map> <entry key="hobby" value="聊天" /> <entry key="clazz" value-ref="clazz"/> </map> </property> <property name="props"> <props> <prop key="desc">我很帅</prop> <prop key="secret">我有两个女朋友</prop> </props> </property> </bean> 6.4.4 注入Properties @Data public class Person { private String name; private List<String> friendNames; private Properties props; } <bean name="p" class="com.qf.spring.ioc.model.Person"> <property name="name" value="李刚" /> <property name="friendNames"> <set> <value>李四</value> <value>王五</value> </set> </property> <property name="props"> <props> <prop key="desc">我很帅</prop> <prop key="secret">我有两个女朋友</prop> </props> </property> </bean> [72ebd55397834d5599e943dfee3c3f33.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/18/613daa33a323478782f169a9c2575efa.png
还没有评论,来说两句吧...