【Spring】——Spring概述、IOC、IOC创建对象的方式、Spring配置、依赖注入(DI)以及自动装配知识

🎼个人主页:【Y小夜】

😎作者简介:一位双非学校的大二学生,编程爱好者,

专注于基础和实战分享,欢迎私信咨询!

🎆入门专栏:🎇【 MySQLJava基础Rust

🎈热门专栏:🎊【 PythonJavawebVue框架

++感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️++

目录

[🎯 Spring概述](#🎯 Spring概述)

😎Spring简介

😎优缺点

😎组成

[🎯 IOC](#🎯 IOC)

😎本质

🎯IOC创建对象方式

😎无参构造

😎有参构造方法

🎯Spring配置

😎Bean的配置

🎯依赖注入(DI)

😎set注入

✨Bean注入

[✨ 数组注入](#✨ 数组注入)

✨List注入

✨Map注入

✨set注入

😎Bean的作用域

✨Singleton模式

😎Prototype模式

🎯自动装配

😎重点

😎byName

😎byType

😎使用注解

✨Autowired

✨Qualifier

✨@Resource

😎小结


🎯 Spring概述

😎Spring简介

Spring是一个轻量级、开源的Java EE应用程序框架,旨在解决企业级应用开发的复杂性,提供一种快速、可重用、易于测试的开发模式

Spring由Rod Johnson在2002年发起,并在2004年正式发布了1.0版本。它通过其核心功能------控制反转(IoC)和面向切面编程(AOP),极大地简化了Java应用的开发过程。

作为一个分层架构的全栈框架,Spring包含多个模块,从数据访问到业务层,再到表现层,几乎涵盖了开发过程中的所有方面。其中,Core Container是整个框架的基础,包括BeanFactory接口和上下文模块。BeanFactory使用控制反转模式,将对象的创建和管理交由Spring容器负责,从而降低了应用组件之间的耦合度。

Spring的AOP模块则提供了强大的支持,允许开发者在不修改原有业务逻辑的情况下,添加或修改系统级别的服务,如事务管理和安全控制。这使得代码的可重用性和可测试性得到了显著提升。

😎优缺点

  • 优点
    1. 方便解耦:通过Spring提供的IoC(控制反转)容器,对象的依赖关系可以交由Spring进行控制,避免硬编码所造成的过度耦合。这样,开发者可以更专注于业务逻辑的设计和实现。
    2. 面向切面编程:Spring的AOP(面向切面编程)功能,使开发者能够以声明式方式进行事务管理、权限拦截和运行监控等功能,显著提高开发效率和质量。
    3. 声明式事务支持:Spring提供了强大的声明式事务管理支持,使得原本繁琐的事务管理代码变得简单且易于维护。
    4. 集成各种框架:Spring可以与Struts、Hibernate、MyBatis等多种优秀的开源框架无缝集成,降低这些框架的使用难度,提升整体开发效率。
    5. 降低API使用难度:Spring对JavaEE API(如JDBC、JavaMail等)进行了薄薄的封装层,使得这些API的使用难度大为降低。
  • 缺点
    1. 学习曲线陡峭:Spring框架功能强大且内容丰富,涉及众多概念和技术,初学者需要花费大量时间来掌握。
    2. 配置文件较多:Spring需要管理多个配置文件,如果设置不当,可能导致应用程序出现各种问题,排查和修复这些问题可能比较麻烦。
    3. 运行效率相对较低:由于Spring提供了丰富的功能和组件,其运行效率可能低于一些轻量级框架,但在现代计算机硬件的支持下,这种差异通常可以忽略不计。
    4. 代码量较大:使用Spring意味着需要编写和维护更多的代码,这可能会增加项目的复杂度和维护难度。
    5. 版本更新较快:Spring的版本更新频繁,新版本可能引入新功能同时废弃旧功能,这要求开发者不断适应和学习。

😎组成


Spring 框架是一个分层架构,由 7 个定义良好的模块组成。 Spring 模块构建在核心容器之上,核心容器 定义了创建、配置和管理 bean 的方式 .

  1. 核心容器
    • spring-core模块:提供框架的基本组成部分,包括控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)功能。
    • spring-beans模块:提供BeanFactory,管理被称为"Bean"的对象。
    • spring-context模块:建立在Core和Beans模块之上,提供对象访问方式,并通过ApplicationContext接口进行访问。
    • spring-context-support模块:整合第三方库到Spring应用程序上下文,支持高速缓存和任务调度。
    • spring-expression模块:提供表达式语言以支持运行时查询和操作对象图。
  2. AOP和仪器支持
    • spring-aop模块:提供面向切面的编程实现,允许定义方法拦截器和切入点。
    • spring-aspects模块:与AspectJ集成,一个成熟的AOP框架。
    • spring-instrument模块:提供类植入支持和特定应用服务器中的类加载器实现。
  3. 数据访问与集成
    • spring-jdbc模块:提供JDBC抽象层,简化数据库操作。
    • spring-orm模块:集成Hibernate、JPA和JDO等ORM框架。
    • spring-oxm模块:提供Object-to-XML-Mapping的抽象层。
    • spring-jms模块:包含生产和使用消息的功能,自Spring4.1起,与spring-messaging模块集成。
    • spring-tx模块:事务模块,支持编程和声明式事务管理。
  4. Web
    • spring-websocket模块:实现双工异步通讯协议,提供Socket通信和推送功能。
    • spring-webmvc模块:包含Spring MVC和REST Web Services实现。
    • spring-web模块:提供基本Web开发集成功能,如文件上传支持和Filter类。
  5. 消息
    • spring-messaging模块:自Spring4.0新增,提供消息传递体系结构和协议支持。
  6. 测试
    • spring-test模块:支持使用JUnit或TestNG对Spring组件进行单元和集成测试。

🎯 IOC

😎本质

控制反转IoC(Inversion of Control) ,是一种设计思想, DI( 依赖注入 ) 是实现 IoC 的一种方法 ,也有人认 为DI 只是 IoC 的另一种说法。没有 IoC 的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系 完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为 所谓控制反转就是:获得依赖对象的方式反转了。

控制反转是一种通过描述(XML 或注解)并通过第三方去生产或获取特定对象的方式。在 Spring 中实现 控制反转的是 IoC 容器,其实现方法是依赖注入( Dependency Injection,DI )。

🎯IOC****创建对象方式

😎无参构造

实体类

java 复制代码
public class User {
private String name;
public User() {
System.out.println("user无参构造方法");
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}

XML文件

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">
<bean id="user" class="com.aaa.pojo.User">
<property name="name" value="kkk"/>
</bean>
</beans>

测试类

java 复制代码
@Test
public void test(){
ApplicationContext context = new
ClassPathXmlApplicationContext("beans.xml");
//在执行getBean的时候, user已经创建好了 , 通过无参构造
User user = (User) context.getBean("user");
//调用对象的方法 .
user.show();
}

😎有参构造方法

java 复制代码
public class UserT {
private String name;
public UserT(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}

beans.xml 有三种方式编写

XML 复制代码
<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.aaa.pojo.UserT">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="aaa"/>
</bean>
XML 复制代码
<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.aaa.pojo.UserT">
<!-- name指参数名 -->
<constructor-arg name="name" value="aaa"/>
</bean>
XML 复制代码
<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.aaa.pojo.UserT">
<constructor-arg type="java.lang.String" value="aaa"/>
</bean>

🎯Spring配置

😎Bean****的配置

XML 复制代码
<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.aaa.pojo.Hello">
<prop

🎯依赖注入(DI

依赖注入(DI)是一种通过将对象间的依赖关系转移给外部容器来管理的设计模式,以减少对象间的耦合性并提高代码的可重用性和可维护性

在软件开发中,依赖注入主要解决的是对象之间复杂的依赖关系,以及如何将这些依赖关系管理得更加灵活和可扩展。通过将对象的创建和依赖关系的管理交给外部容器,依赖注入不仅降低了组件之间的耦合度,还提高了系统的可测试性和灵活性。

😎set****注入

常量注入

XML 复制代码
<bean id="student" class="com.aaa.pojo.Student">
<property name="name" value="小明"/>
</bean>

测试

java 复制代码
@Test
public void test01(){
ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}

Bean****注入

注意点:这里的值是一个引用, ref

XML 复制代码
<bean id="addr" class="com.aaa.pojo.Address">
<property name="address" value="重庆"/>
</bean>
<bean id="student" class="com.aaa.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
</bean>

数组注入

XML 复制代码
<bean id="student" class="com.aaa.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
<property name="books">
<array>
<value>西游记</value>
<value>红楼梦</value>
<value>水浒传</value>
</array>
</property>
</bean>

✨List****注入

XML 复制代码
<property name="hobbys">
<list>
<value>听歌</value>
<value>看电影</value>
<value>爬山</value>
</list>
</property>

✨Map****注入

XML 复制代码
<property name="card">
<map>
<entry key="中国邮政" value="456456456465456"/>
<entry key="建设" value="1456682255511"/>
</map>
</property>

✨set****注入

XML 复制代码
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
<value>COC</value>
</set>
</property>

😎Bean****的作用域

✨Singleton模式

当一个bean 的作用域为 Singleton ,那么 Spring IoC 容器中只会存在一个共享的 bean 实例,并且所有对 bean的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。 Singleton是单例类型,就是 在创建起容器时就同时自动创建了一个bean **的对象,不管你是否使用,他都存在了,每次获取到的对象 都是同一个对象。**注意,Singleton 作用域是 Spring 中的缺省作用域。要在 XML 中将 bean 定义成 singleton,可以这样配置:

XML 复制代码
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">

😎Prototype模式

当一个bean 的作用域为 Prototype ,表示一个 bean 定义对应多个对象实例。 Prototype作用域的bean会 导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。 Prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是 当我们获取bean 的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经 验,对有状态的bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。在 XML中将 bean 定义成 prototype ,可以这样配置:

XML 复制代码
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
或者
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/>

🎯自动装配

😎重点

  • 自动装配是使用spring满足bean依赖的一种方法
  • spring会在应用上下文中为某个bean寻找其依赖的bean。

Spring 中 bean 有三种装配机制,分别是:

  1. 在 xml 中显式配置;
  2. 在 java 中显式配置;
  3. 隐式的 bean 发现机制和自动装配。
    这里我们主要讲第三种:自动化的装配 bean 。
    Spring 的自动装配需要从两个角度来实现,或者说是两个操作:
  • 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
  • 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;

组件扫描和自动装配组合发挥巨大威力,使的显示的配置降低到最少。
推荐不使用自动装配 xml 配置 , 而使用注解

😎byName

autowire byName (按名称自动装配 )
由于在手动配置xml 过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。
采用自动装配将避免这些错误,并且使配置简单化。
测试:

  1. 修改 bean 配置,增加一个属性 autowire="byName"
XML 复制代码
<bean id="user" class="com.aaa.pojo.User" autowire="byName">
<property name="str" value="qinjiang"/>
</bean>

当一个 bean 节点带有 autowire byName 的属性时。

  1. 将查找其类中所有的 set 方法名,例如 setCat ,获得将 set 去掉并且首字母小写的字符串,即 cat 。
  2. 去 spring 容器中寻找是否有此字符串名称 id 的对象。
  3. 如果有,就取出注入;如果没有,就报空指针异常。

😎byType

autowire byType ( 按类型自动装配 )
使用 autowire byType 首先需要保证:同一类型的对象,在 spring 容器中唯一。如果不唯一,会报不唯一 的异常。
测试:

XML 复制代码
<bean id="dog" class="com.aaa.pojo.Dog"/>
<bean id="cat" class="com.aaa.pojo.Cat"/>
<bean id="cat2" class="com.aaa.pojo.Cat"/>
<bean id="user" class="com.aaa.pojo.User" autowire="byType">
<property name="str" value="qinjiang"/>
</bean>

😎使用注解

**✨**Autowired

@Autowired 是按类型自动转配的,不支持 id 匹配。
需要导入 spring-aop 的包!

XML 复制代码
<context:annotation-config/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User"/>
java 复制代码
@Autowired(required = false)
private Cat cat;

✨Qualifier

@Autowired 是根据类型自动装配的,加上 @Qualifier 则可以根据 byName 的方式自动装配
@Qualifier 不能单独使用。

java 复制代码
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;

@Resource

@Resource 如有指定的 name 属性,先按该属性进行 byName 方式查找装配;
其次再进行默认的 byName 方式进行装配;
如果以上都不成功,则按 byType 的方式自动装配。
都不成功,则报异常。

java 复制代码
@Resource
private Cat cat;
@Resource
private Dog dog;

😎小结

@Autowired与@Resource异同:

  1. @Autowired与 @Resource 都可以用来装配 bean 。都可以写在字段上,或写在 setter 方法上。
  2. @Autowired默认按类型装配(属于 spring 规范),默认情况下必须要求依赖对象必须存在,如果 要允许null 值,可以设置它的 required 属性为 false ,如: @Autowired(required=false) ,如果我 们想使用名称装配可以结合@Qualifier 注解进行使用
  3. @Resource(属于 J2EE 复返),默认按照名称进行装配,名称可以通过 name 属性进行指定。如果 没有指定name 属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在 setter方法上默认取属性名进行装配。 当找不到与名称匹配的 bean 时才按照类型进行装配。但是 需要注意的是,如果name 属性一旦指定,就只会按照名称进行装配。
    它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired 先byType,@Resource先 byName。
相关推荐
Asthenia041243 分钟前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9651 小时前
ovs patch port 对比 veth pair
后端
Asthenia04121 小时前
Java受检异常与非受检异常分析
后端
uhakadotcom1 小时前
快速开始使用 n8n
后端·面试·github
JavaGuide2 小时前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9652 小时前
qemu 网络使用基础
后端
Asthenia04122 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04122 小时前
Spring 启动流程:比喻表达
后端
Asthenia04123 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua3 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫