SpringIOC讲解

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: SpringIOC讲解

1.Spring简介


Spring框架由Rod Johnson开发,2004年发布了Spring框架的第一版。Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高了企业应用的开发效率。


Spring总结起来优点如下:


低侵入式设计,代码的污染极低。

独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺。

Spring的IoC容器降低了业务对象替换的复杂性,提高了组件之间的解耦。

Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用。

Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问。

Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部。

Spring框架的组成结构图如下所示:


7931c7dfc459836b9426be31949c69a6.png


Core 容器


Core 容器由 Core、Beans、Context 和 Expression Language 模块组成,详细信息如下 −


Core 模块提供了框架的基本部分,包括 IoC 和依赖注入功能。


Bean 模块提供了 BeanFactory,它是工厂模式的一个复杂的实现。


Context 模块建立在 Core 和 Beans 模块提供的坚实基础之上,它是访问任何已定义和配置的对象的媒介。 ApplicationContext 接口是上下文模块的焦点。


SpEL 模块提供了一种强大的表达式语言,用于在运行时查询和操作对象图。

数据访问/集成


数据访问/集成层由 JDBC、ORM、OXM、JMS 和 Transaction 事务模块组成,详细信息如下 −


JDBC 模块提供了一个 JDBC 抽象层,它消除了繁琐的 JDBC 相关编码的需要。


ORM 模块为流行的对象关系映射 API 提供集成层,包括 JPA、JDO、Hibernate 和 iBatis。


OXM 模块提供了一个抽象层,它支持 JAXB、Castor、XMLBeans、JiBX 和 XStream 的 Object/XML 映射实现。


Java 消息传递服务 JMS 模块包含用于生成和使用消息的功能。


Transaction 模块支持对实现特殊接口的类和所有 POJO 的编程和声明式事务管理。

Web


Web 层由 Web、Web-MVC、Web-Socket 和 Web-Portlet 模块组成,具体如下 −


Web 模块提供了基本的面向 Web 的集成功能,例如多部分文件上传功能以及使用 servlet 侦听器和面向 Web 的应用程序上下文初始化 IoC 容器。


Web-MVC 模块包含 Spring 的 Web 应用程序的 Model-View-Controller(模型-视图-控制器) (MVC) 实现。


Web-Socket 模块支持 Web 应用程序中客户端和服务器之间基于 WebSocket 的双向通信。


Web-Portlet 模块提供了在portlet 环境中使用的MVC 实现,并反映了Web-Servlet 模块的功能。

杂项


其他重要的模块很少,如 AOP、Aspects、Instrumentation、Web 和 Test 模块,具体如下 −


AOP 模块提供了一个面向方面的编程实现,允许您定义方法拦截器和切入点,以清晰地解耦实现应该分离的功能的代码。


Aspects 模块提供与 AspectJ 的集成,AspectJ 又是一个强大且成熟的 AOP 框架。


Instrumentation 模块提供类检测支持和类加载器实现以用于某些应用程序服务器。


Messaging 模块支持将 STOMP 作为 WebSocket 子协议在应用程序中使用。 它还支持注解编程模型,用于路由和处理来自 WebSocket 客户端的 STOMP 消息。


Test 模块支持使用 JUnit 或 TestNG 框架对 Spring 组件进行测试。

2.为什么要学习 Spring?


Spring 是最流行的企业 Java 应用程序开发框架。 全球数以百万计的开发人员使用 Spring 框架来创建高性能、易于测试和可重用的代码。


Spring 框架是一个开源的 Java 平台。 它最初由 Rod Johnson 编写,并于 2003 年 6 月在 Apache 2.0 许可下首次发布。


在大小和透明度方面,Spring 是轻量级的。 Spring 框架的基本版本约为 2MB。


Spring 框架的核心特性可用于开发任何 Java 应用程序,但也有一些扩展可用于在 Java EE 平台之上构建 Web 应用程序。 Spring 框架旨在通过启用基于 POJO 的编程模型使 J2EE 开发更易于使用并促进良好的编程实践

3.Spring 的应用


以下是使用 Spring 框架的几个巨大好处的列表 −


究竟什么是依赖注入? 我们分别来看这两个词。 这里依赖部分转化为两个类之间的关联。 例如,A 类依赖于 B 类。现在,我们来看第二部分,注入。 这意味着,B 类将被 IoC 注入到 A 类中。


依赖注入可以通过将参数传递给构造函数的方式发生,也可以通过使用 setter 方法的构造后发生。 由于依赖注入是 Spring 框架的核心,我们将在单独的章节中用相关示例解释这个概念。

面向方面的编程(AOP)


Spring 的关键组件之一是面向方面编程 (AOP) 框架。 跨越应用程序多个点的功能称为横切关注点,这些横切关注点在概念上与应用程序的业务逻辑分开。 有各种常见的好例子,包括日志记录、声明式事务、安全性、缓存等。


OOP 中模块化的关键单元是类,而 AOP 中模块化的单元是方面。 DI 可帮助您将应用程序对象彼此分离,而 AOP 可帮助您将横切关注点与它们影响的对象分离。


Spring 框架的 AOP 模块提供了面向方面的编程实现,允许您定义方法拦截器和切入点,以清晰地解耦实现应该分离的功能的代码。 我们将在单独的章节中讨论更多关于 Spring AOP 的概念。

依赖注入 (DI)


Spring 最受认同的技术是控制反转的依赖注入 (DI) 风格。 Inversion of Control (IoC) 控制反转是一个通用概念,可以用多种不同的方式表达。 依赖注入只是控制反转的一个具体例子。


在编写复杂的 Java 应用程序时,应用程序类应尽可能独立于其他 Java 类,以增加重用这些类的可能性,并在单元测试时独立于其他类对其进行测试。 依赖注入有助于将这些类粘合在一起,同时保持它们的独立性。


基于 POJO - Spring 使开发人员能够使用 POJO 开发企业级应用程序。 仅使用 POJO 的好处是您不需要 EJB 容器产品,例如应用程序服务器,但您可以选择仅使用强大的 servlet 容器,例如 Tomcat 或某些商业产品。


模块化 - Spring 以模块化方式组织。 即使包和类的数量很多,您也只需要担心您需要的,而忽略其余的。


与现有框架集成 - Spring 并没有重新发明,而是真正利用了一些现有技术,如几个 ORM 框架、日志框架、JEE、Quartz 和 JDK 计时器以及其他视图技术。


可测试性 - 测试用 Spring 编写的应用程序很简单,因为依赖于环境的代码被移到了这个框架中。 此外,通过使用 JavaBeanstyle POJO,使用依赖注入来注入测试数据变得更加容易。


Web MVC - Spring 的 web 框架是一个设计良好的 web MVC 框架,它为 Struts 等 web 框架或其他过度设计或不太流行的 web 框架提供了一个很好的替代方案。


中央异常处理 - Spring 提供了一个方便的 API 来将特定于技术的异常(例如,由 JDBC、Hibernate 或 JDO 抛出)转换为一致的、未经检查的异常。


轻量级 - 轻量级 IoC 容器往往是轻量级的,例如,与 EJB 容器相比时尤其如此。 这有利于在内存和 CPU 资源有限的计算机上开发和部署应用程序。


事务管理 - Spring 提供一致的事务管理接口,可以缩小到本地事务(例如,使用单个数据库)并扩展到全局事务(例如,使用 JTA)。

4使用 Spring 框架的好处


以下是使用 Spring 框架的几个巨大好处的列表 −


Spring 使开发人员能够使用 POJO 开发企业级应用程序。 仅使用 POJO 的好处是您不需要 EJB 容器产品(例如应用程序服务器),但您可以选择仅使用健壮的 servlet 容器(例如 Tomcat 或某些商业产品)。


Spring 以模块化方式组织。 即使包和类的数量很多,您也只需要担心您需要的,而忽略其余的。


Spring 并没有重新发明,而是真正利用了一些现有的技术,如几个 ORM 框架、日志框架、JEE、Quartz 和 JDK 计时器以及其他视图技术。


测试使用 Spring 编写的应用程序很简单,因为依赖于环境的代码已移至此框架。 此外,通过使用 JavaBeanstyle POJO,更容易使用依赖注入来注入测试数据。


Spring 的 web 框架是一个设计良好的 web MVC 框架,它为 Struts 等 web 框架或其他过度设计或不太流行的 web 框架提供了一个很好的替代方案。


Spring 提供了一个方便的 API 来将特定于技术的异常(例如,由 JDBC、Hibernate 或 JDO 抛出)转换为一致的、未经检查的异常。


轻量级 IoC 容器往往是轻量级的,例如,与 EJB 容器相比时尤其如此。 这有利于在内存和 CPU 资源有限的计算机上开发和部署应用程序。


Spring 提供了一个一致的事务管理接口,可以缩小到本地事务(例如使用单个数据库)并扩展到全局事务(例如使用 JTA)。

5.Spring中的ioc

IOC是什么?

基本定义/主要思想:Spring中的IOC(控制反转)是一种设计模式,它通过将对象的创建和依赖关系的管理交给容器来实现对象之间的解耦。


现实生活中的例子或类比:想象一下,你正在组装一辆自行车。如果你手动组装每个部件并处理它们之间的依赖关系,那么这将是一项繁琐的任务。相反,如果你将这些部件交给一个专业的自行车制造商来组装,他们会负责创建和管理所有的部件,你只需要使用最终的自行车即可。在这个例子中,自行车制造商就是IOC容器,它负责创建和管理对象,而你只需要使用这些对象。


总结:Spring中的IOC是一种通过将对象的创建和依赖关系的管理交给容器来实现对象解耦的设计模式。

IOC主要功能

Spring IOC(Inversion of Control,控制反转)是Spring框架的核心功能之一,它的主要功能是管理和控制应用程序中的对象的创建、依赖注入和生命周期管理。


具体来说,Spring IOC的主要功能包括:


1. 对象的创建:Spring IOC负责管理和创建应用程序中的对象,通过配置文件或注解来定义对象的创建方式和属性。


2. 依赖注入:Spring IOC可以自动将对象之间的依赖关系注入到对象中,无需手动编写代码来实现依赖关系的管理。


3. 生命周期管理:Spring IOC可以管理对象的生命周期,包括对象的初始化、使用和销毁等阶段。通过配置文件或注解,可以定义对象的初始化方法和销毁方法。


4. 松耦合:Spring IOC通过控制对象的创建和依赖注入,实现了对象之间的松耦合。对象只需要关注自己的功能实现,而不需要关心如何创建和获取其他对象。


5. 配置灵活性:Spring IOC通过配置文件或注解来定义对象的创建和依赖关系,提供了很大的灵活性。可以根据实际需求,灵活地配置对象的属性和依赖关系。


总的来说,Spring IOC的主要功能是提供对象的创建、依赖注入和生命周期管理,实现了对象之间的松耦合和配置的灵活性。这使得应用程序的开发和维护变得更加简单和高效。

案例

UserService 接口

package com.liao.ioc.service;
public interface UserService {
    public String update();
}


UserServiceImpl 实现类

package com.liao.ioc.service.impl;
import com.liao.ioc.service.UserService;
public class UserServiceImpl implements UserService {
    public String update(){
        //如果已经修改用户信息方法
        System.out.println("修改个人用户信息");
        return "list";
    }
}


UserServiceImpl2 实现类

package com.liao.ioc.service.impl;
import com.liao.ioc.service.UserService;
public class UserServiceImpl2 implements UserService {
    public String update(){
        System.out.println("修改个人用户信息");
        System.out.println("更改用户头像信息");
        return "list";
    }
}


GoodsAction 控制器

package com.CloudJun.ioc.web;
import com.liao.ioc.service.UserService;
import com.liao.ioc.service.impl.UserServiceImpl;
public class GoodsAction {
    public UserService getUserService() {
        return userService;
    }
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    /**
     * 例如:在不同的控制器中进行方法调用
     */
    private UserService userService;
    public String update(){
        userService.update();
        return "list";
    }
}


UserAction 控制器

package com.liao.ioc.web;
import com.liao.ioc.service.UserService;
import com.liao.ioc.service.impl.UserServiceImpl;
public class UserAction {
    /**
     * 手动实例化的弊端
     *  1.如果依赖的接口实现需要大批量改动及迭代时,维护的成本极高
     *  2.当接口的实现类不统一,维护成本更高
     */
    private UserService userService ;
    public UserService getUserService() {
        return userService;
    }
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public String update(){
         userService.update();
         return "list";
     }
}


spring-context.xml 配置文件

注入方式

set注入


set注入是基于set方法注入的,它的底层是通过反射机制调用属性对应的set方法给属性赋值,这种方式必须要求属性对外提供set方法,让两个对象之间产生关系。

package com.liao.ioc.web;
import com.liao.ioc.service.UserService;
import java.util.List;
public class GoodsAction {
    /**
     * 例如:在不同的控制器中进行方法调用
     */
    private UserService userService;
    private String gname;
    private int age;
    private List<String> peoples;
    public String getGname() {
        return gname;
    }
    public void setGname(String gname) {
        this.gname = gname;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public List<String> getPeoples() {
        return peoples;
    }
    public void setPeoples(List<String> peoples) {
        this.peoples = peoples;
    }
    public UserService getUserService() {
        return userService;
    }
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void pop(){
        System.out.println("名称:"+this.gname);
        System.out.println("年龄:"+this.age);
        System.out.println("使用人:"+this.peoples);
    }
    public String update(){
        userService.update();
        return "list";
    }
}



spring-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byName"
       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 class="com.liao.ioc.web.UserAction" id="userAction">
         <property name="userService" ref="userServiceImpl"></property>
        </bean>
        <bean class="com.liao.ioc.web.GoodsAction" id="goodsAction">
            <property name="userService" ref="userServiceImpl2"></property>
            <property name="gname" value="赵六"></property>
            <property name="age" value="18"></property>
            <property name="peoples">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                </list>
            </property>
        </bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl" id="userService" ></bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl2" id="userServiceImpl2"></bean>
</beans>


构造注入

核心原理:通过调用构造方法来给属性赋值。

package com.liao.ioc.web;
import com.liao.ioc.service.UserService;
import java.util.List;
public class UserAction {
    /**
     * 手动实例化的弊端
     *  1.如果依赖的接口实现需要大批量改动及迭代时,维护的成本极高
     *  2.当接口的实现类不统一,维护成本更高
     */
    private UserService userService ;
    private  String uname;
    private  int age;
    private List<String> hobby;
    public UserAction() {
    }
    public UserAction(String uname, int age, List<String> hobby) {
        this.uname = uname;
        this.age = age;
        this.hobby = hobby;
    }
    public UserService getUserService() {
        return userService;
    }
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void pop(){
        System.out.println("名字为:"+this.uname);
        System.out.println("年龄为:"+this.age);
        System.out.println("爱好为:"+this.hobby);
    }
    public String update(){
         userService.update();
         return "list";
     }
}


spring-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byName"
       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">
<!--    在spring配置文件spring-context.xml中配置,那么该类javabean就交给spring容器管理 -->
        <bean class="com.liao.ioc.web.UserAction" id="userAction">
            <property name="userService" ref="userService"></property>
            <constructor-arg name="uname" value="奥特曼" ></constructor-arg>
            <constructor-arg name="age" value="66" ></constructor-arg>
            <constructor-arg name="hobby"  >
                <list>
                    <value>打飞机</value>
                    <value>打篮球</value>
                </list>
            </constructor-arg>
        </bean>
          <bean class="com.liao.ioc.web.GoodsAction" id="goodsAction">
            <property name="userService" ref="userServiceImpl2"></property>
            <property name="gname" value="赵六"></property>
            <property name="age" value="18"></property>
            <property name="peoples">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                </list>
            </property>
        </bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl" id="userService" ></bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl2" id="userServiceImpl2"></bean>
</beans>


接口注入

自动装配

       byName:根据bean的id在Spring的上下文进行寻找


  byType:根据属性接口在Spring上下文找对应的接口实现类

byName

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byName"
       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">
<!--    在spring配置文件spring-context.xml中配置,那么该类javabean就交给spring容器管理 -->
        <bean class="com.liao.ioc.web.UserAction" id="userAction">
            <property name="userService" ref="userService"></property>
            <constructor-arg name="uname" value="奥特曼" ></constructor-arg>
            <constructor-arg name="age" value="66" ></constructor-arg>
            <constructor-arg name="hobby"  >
                <list>
                    <value>打飞机</value>
                    <value>打篮球</value>
                </list>
            </constructor-arg>
        </bean>
          <bean class="com.liao.ioc.web.GoodsAction" id="goodsAction">
            <property name="userService" ref="userServiceImpl2"></property>
            <property name="gname" value="赵六"></property>
            <property name="age" value="18"></property>
            <property name="peoples">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                </list>
            </property>
        </bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl" id="userService" ></bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl2" id="userServiceImpl2"></bean>
</beans>


byType

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byType"
       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">
<!--    在spring配置文件spring-context.xml中配置,那么该类javabean就交给spring容器管理 -->
        <bean class="com.liao.ioc.web.UserAction" id="userAction">
            <property name="userService" ref="userService"></property>
            <constructor-arg name="uname" value="奥特曼" ></constructor-arg>
            <constructor-arg name="age" value="66" ></constructor-arg>
            <constructor-arg name="hobby"  >
                <list>
                    <value>打飞机</value>
                    <value>打篮球</value>
                </list>
            </constructor-arg>
        </bean>
          <bean class="com.liao.ioc.web.GoodsAction" id="goodsAction">
            <property name="userService" ref="userServiceImpl2"></property>
            <property name="gname" value="赵六"></property>
            <property name="age" value="18"></property>
            <property name="peoples">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                </list>
            </property>
        </bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl" id="userService" ></bean>
        <bean class="com.liao.ioc.service.impl.UserServiceImpl2" id="userServiceImpl2"></bean>
</beans>


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
XML 前端开发 Java
1.5 Spring注解
在Spring框架中,尽管使用xml配置文件可以简单的装配Bean,但如果应用中有大量的Bean需要装配时,会导致xml配置文件过于庞大和繁重,影响开发效率,所以推荐使用注解(annotation)代替xml配置文件,可以简化配置,提高开发效率。
66 0
|
6月前
|
人工智能 运维 Java
SpringIoC原理
SpringIoC原理
34 2
|
6月前
|
前端开发 Java 数据格式
Spring注解详解
Spring注解详解
53 0
|
XML druid Java
SpringIoC和DI注解开发
SpringIoC和DI注解开发
45 0
|
XML Java 数据格式
SpringIoC基于注解配置
一、Bean注解标记和扫描 (IoC) 二、组件(Bean)作用域和周期方法注解 三、Bean属性赋值:引用类型自动装配 (DI) 四、Bean属性赋值:基本类型属性赋值 (DI)
63 0
|
XML druid Java
02-SpringIoC和DI注解开发
02-SpringIoC和DI注解开发
02-SpringIoC和DI注解开发
|
Java Spring
springIOC-spring源码详解(二)
springIOC-spring源码详解(二)
springIOC-spring源码详解(二)
|
XML Java 数据格式
【Spring源码解析】SpringIOC(1)—— Bean与BeanDefinition
全局视角看核心接口和类 Bean与BeanDefinition BeanDefinition是Bean的定义 容器初始化主要做的事情(主要脉络) BeanDefinition源码
【Spring源码解析】SpringIOC(1)—— Bean与BeanDefinition
|
XML Java 数据格式
【关于Spring那些事】——SpringIoC基于注解的配置
在Spring容器中我们可以使用XML配置实现Bean的装配,但是如果Bean过多,则会显得XML文件过于臃肿,为后续的工作造成了一定的困难,因此Spring提供了一种基于注解(Annotation)的装配方式。
120 0