简介
Spring是一个开源的、轻量级的Java开发框架,旨在简化企业级应用开发。
Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在 2002 年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用型框架 。 [2]Spring是一个开源容器框架,它集成各类型的工具,通过核心的Bean factory实现了底层的类的实例化和生命周期的管理。在整个框架中,各类型的功能被抽象成一个个的 Bean,这样就可以实现各种功能的管理,包括动态加载和切面编程。 [3]Spring是独特的,因为若干个原因: 它定位的领域是许多其他流行的framework没有的。Spring致力于提供一种方法管理你的业务对象。 Spring是全面的和模块化的。Spring有分层的体系结构,这意味着你能选择使用它孤立的任何部分,它的架构仍然是内在稳定的。例如,你可能选择仅仅使用Spring来简单化JDBC的使用,或用来管理所有的业务对象。 它的设计从底部帮助你编写易于测试的代码。Spring是用于测试驱动工程的理想的framework。 Spring对你的工程来说,它不需要一个以上的framework。Spring是潜在地一站式解决方案,定位于与典型应用相关的大部分基础结构。它也涉及到其他framework没有考虑到的内容。
Spring框架优缺点
优点
- 依赖注入(DI)和面向切面编程(AOP):
- 依赖注入(DI):Spring允许通过依赖注入来管理对象的生命周期和依赖关系,减少了对象间的耦合,提高了代码的可维护性和测试性。
- 面向切面编程(AOP):提供了对跨越多个对象的关注点(如事务处理、安全性)的支持,使代码更加模块化。
- 模块化:
- Spring框架由多个模块组成(如Spring Core, Spring MVC, Spring Data, Spring Security等),可以根据需要选择性地使用。
- 开箱即用:
- 提供了多种开箱即用的功能,如事务管理、数据访问、消息传递等,简化了开发过程。
- 灵活性和可扩展性:
- Spring支持多种配置方式(XML、Java配置、注解等),允许开发者根据需求选择最适合的方式。
- Spring框架本身具有很高的灵活性和可扩展性,它允许开发者根据需要选择适合的功能和组件,并且可以与其他框架如Hibernate、MyBatis等集成,提供更加灵活和强大的应用开发能力。
- 与其他技术兼容:
- 与各种技术和框架(如Hibernate、JPA、JMS、Quartz等)兼容,提供了广泛的集成支持。
- 社区支持和文档:
- 拥有活跃的社区支持和详细的文档,有助于解决开发过程中的问题和学习框架。
- 测试支持:
- 提供了对单元测试和集成测试的支持,简化了测试的编写和执行。
- 事务管理:
- 支持声明式事务管理,允许开发者以声明的方式处理事务,提高了事务管理的灵活性和可控性。
缺点
- 学习曲线:
- Spring框架的学习曲线较陡,特别是对初学者来说。理解和掌握其核心概念(如DI、AOP)和相关配置可能需要时间。
- 复杂性:
- 大型Spring应用程序可能会变得复杂,配置和管理的难度也会增加,尤其是在使用多个模块和集成时。
- 配置文件较多:
- Spring框架需要管理大量的配置文件,这些文件必须进行恰当的设置和管理,否则可能导致应用程序出现各种问题。
- 性能开销:
- 由于依赖注入和AOP等功能可能引入额外的性能开销,尽管在大多数情况下这种开销是可以接受的,但在高性能要求的场景下需谨慎使用。
- 配置管理:
- 尽管Spring提供了多种配置方式,但在大型项目中,配置文件和类的管理可能会变得繁琐。
- 过度使用:
- 在某些情况下,Spring框架的功能可能被过度使用,导致项目过度复杂化或引入不必要的功能。
- 版本兼容性:
- 随着Spring框架的版本更新,某些功能和配置可能会发生变化,这可能导致现有代码的兼容性问题。
- Spring框架频繁更新,新版本的发布可能会引入破坏性变更,需要开发者不断学习和适应。
Spirng 核心
1、IOC(Inversion of Control,控制反转)
IOC是Spring容器的核心,它并不是一种技术,而是一种设计思想。IOC将对象的使用和创建分开,把对象的创建和生命周期的管理,以及相关的依赖资源获取等控制权,反转给Spring容器,而不是由对象自身管理。这有助于降低代码之间的耦合度,提高模块化和可维护性。
具体来说,IOC在Spring中可以理解为一个Map容器,用于存放和管理Bean对象,并控制Bean的生命周期。当服务启动时,JVM会扫描jar包或war包中的class文件,找到配置类,并将加了相关注解的实例Bean加入到IOC容器中。这样,开发者在使用对象时,就无需自己创建对象和控制对象的生命周期,只需从IOC容器中获取所需的对象即可。
IOC的主要作用包括:
- 创建对象:IOC容器可以自动创建Bean对象,而无需手动new出对象。
- 管理对象的依赖关系:通过配置文件或注解,可以描述类和类之间的依赖关系,IOC容器会自动完成依赖关系的装配。
- 避免大量单例模式和工厂模式的泛滥:IOC容器可以管理多个Bean对象,并控制它们的生命周期,从而避免了大量单例模式和工厂模式的使用。
IOC的实现方式:
先创建两个类User和Profile类
@Data
public class User {
public User(int id, String username, String password, String email, String name, Profile profile) {
this.id = id;
this.username = username;
this.name = name;
this.password = password;
this.email = email;
this.profile = profile;
}
public User() {
}
private int id;
private String username;
private String name;
private String password;
private String email;
private Profile profile;
}
@Data
public class Profile {
private String name;
private String birthday;
private String address;
private String phoneNumber;
}
- 构造器注入:通过构造器参数传递依赖对象。
构造器注入是通过对象的构造器将依赖项注入到对象中。这种方式确保了对象在创建时就处于完全初始化的状态。
在applicationContext.xml文件添加以下配置
<!-- Bean构造函数注入 1.通过name属性名称进行注入 -->
<bean id="user" class="org.example.model.User">
<constructor-arg value="xx@qq.com" name="email"/>
<constructor-arg value="xx123" name="username"/>
<constructor-arg value="1" name="id"/>
<constructor-arg value="xxxxxxx" name="password"/>
<constructor-arg value="xxx" name="name"/>
<constructor-arg ref="profile" name="profile"/>
</bean>
<!-- Bean构造函数注入 2.通过index下标进行注入 -->
<bean id="user1" class="org.example.model.User">
<constructor-arg value="xx@qq.com" index="3"/>
<constructor-arg value="xx123" index="1"/>
<constructor-arg value="1" index="0"/>
<constructor-arg value="xxxxxxx" index="2"/>
<constructor-arg value="xxx" index="4"/>
<constructor-arg ref="profile" index="5"/>
</bean>
- Setter注入:通过Setter方法设置依赖对象。
Setter注入是通过对象的setter方法将依赖项注入到对象中。这种方式允许在对象创建后更改其依赖项。
在applicationContext.xml文件添加以下配置
<!-- Bean Set注入 -->
<bean id="profile" class="org.example.model.Profile">
<property value="xxx" name="name"/>
<property name="birthday" value="2024-10-25"/>
<property value="xx省xx市xx区" name="address"/>
<property value="135xxxx9586" name="phoneNumber"/>
</bean>
在测试类上面添加以下方法
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:applicationContext.xml"})
public class Test {
// 构造器注入
@org.junit.Test
public void constructorSet(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取应用上下文
User user = (User) context.getBean("user"); // 获取Bean实例,强转为实体类,通过name属性注入
System.out.println("user:" + user);
User user1 = (User) context.getBean("user1"); // 获取Bean实例,强转为实体类,通过index下标进行注入
System.out.println("user1:" + user1);
}
}
启动该方法,获取结果
user:User(id=1, username=xx123, name=xxx, password=xxxxxxx, email=xx@qq.com, profile=Profile(name=xxx, birthday=2024-10-25, address=xx省xx市xx区, phoneNumber=135xxxx9586))
user1:User(id=1, username=xx123, name=xxx, password=xxxxxxx, email=xx@qq.com, profile=Profile(name=xxx, birthday=2024-10-25, address=xx省xx市xx区, phoneNumber=135xxxx9586))
- 字段注入(注解注入):直接在对象字段上使用注解注入依赖。
字段注入是直接在对象的字段上注入依赖项。这种方式简单直接,但不够灵活,因为它不允许在对象创建后更改其依赖项。
@Autowire注解,@Autowire主要有三个属性值:constructor,byName,byType。
constructor: 通过构造方法进行自动注入,spring会匹配与构造方法参数类型一致的bean进行注入,如果有一个多参数的构造方法,一个只有一个参数的构造方法,在容器中查找到多个匹配多参数构造方法的bean,那么spring会优先将bean注入到多参数的构造方法中。
byName: 被注入bean的id名必须与set方法后半截匹配,并且id名称的第一个单词首字母必须小写,这一点与手动set注入有点不同。
byType: 查找所有的set方法,将符合参数类型的bean注入。
@Autowire的局限性和解决方法
-
局限性
- 当通过类型匹配找不到唯一的 Bean 时,Spring 会抛出异常。例如,如果容器中有两个
UserRepository的实现类,且没有明确指定要注入哪一个,就会出现问题。
- 当通过类型匹配找不到唯一的 Bean 时,Spring 会抛出异常。例如,如果容器中有两个
-
解决方法
- 可以使用
@Qualifier注解来指定要注入的 Bean 的名称。例如,如果有UserRepositoryImpl1和UserRepositoryImpl2两个实现类,并且想注入UserRepositoryImpl1,可以这样修改UserService类。 - 实现
@Autowired @Qualifier("userRepositoryImpl1") private UserRepository userRepository; - 可以使用
主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有所差异:
- @Component: 可以用于注册所有bean
- @Repository: 主要用于注册dao层的bean
- @Controller: 主要用于注册控制层的bean
- @Service: 主要用于注册服务层的bean
-
在
User类上面添加@Component注解 -
在测试类上面添加以下方法
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:applicationContext.xml"})
public class Test {
@Resource
private User user;
// 字段注入
@org.junit.Test
public void fieldInjection(){
user.setName("xxx");
user.setId(1);
user.setPassword("xxxx");
user.setUsername("xxxx");
user.setEmail("xxxx@qq.com");
System.out.println("user:" + user);
}
}
测试结果
user:User(id=1, username=xxxx, name=xxx, password=xxxx, email=xxxx@qq.com, profile=Profile(name=xxx, birthday=2024-10-25, address=xx省xx市xx区, phoneNumber=135xxxx9586))
2、AOP(Aspect Oriented Programming,面向切面编程)
概念:
面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP是Spring框架的另一个核心特性,它提供了对横切关注点(如日志、事务管理等)的模块化支持。通过AOP,可以将横切关注点与业务逻辑代码分离,从而提高代码的可维护性和可重用性。
Spring AOP模块提供了满足AOP Alliance规范的实现,并整合了AspectJ这种AOP语言级的框架。通过AOP,可以方便地进行面向切面编程,实现如日志记录、事务管理、权限控制等横切关注点的模块化。
Spirng 7大核心模块
1. Spring Core(核心容器)
1.1 主要功能和特点
- 控制反转(IoC):
- Spring Core 通过 IoC 容器管理应用程序中的对象(称为 Beans)的创建、生命周期和依赖关系。
- 一种设计原则,通过将对象的创建和管理交给容器来实现,应用程序只需要关注业务逻辑,而不需要关心对象的创建和生命周期管理。
- Spring 容器负责创建和管理对象,应用程序可以通过依赖注入的方式获取所需的对象,从而降低了对象之间的耦合度,提高了代码的可维护性和可测试性。
- 依赖注入(DI):
- Spring Core 支持依赖注入,这是一种将对象之间的依赖关系自动连接起来的方法,从而降低了代码的耦合度。
- 管理对象之间的依赖关系,将对象的创建和组装职责从应用代码转移到容器中。通过构造函数注入、Setter 方法注入和字段注入等方式,实现对象之间的松耦合。
- 例如,一个服务类需要依赖一个数据访问对象(DAO),可以在服务类的构造函数中接收 DAO 对象作为参数,或者通过 Setter 方法设置 DAO 对象,Spring 容器会在运行时自动将 DAO 对象注入到服务类中。
- 面向切面编程(Aspect-Oriented Programming,AOP):
- 一种编程思想,将横切关注点(如日志记录、事务管理、安全检查等)从业务逻辑中分离出来,通过切面(Aspect)和通知(Advice)的方式在不修改业务代码的情况下为业务方法添加额外的功能。
- Spring AOP 基于代理模式实现,可以在运行时动态地为目标对象生成代理对象,在代理对象中织入切面逻辑,从而实现对目标对象的增强。
- Bean 工厂:
- 提供了一个中央化的 Bean 工厂,用于配置和管理应用程序中的 Beans。
- Bean 生命周期管理:
- 允许开发者通过实现特定的接口或使用注解来控制 Bean 的生命周期。
- 类型转换和数据绑定:
- 提供了强大的类型转换和数据绑定机制,可以将外部数据(如表单提交的数据)自动转换并绑定到 Java 对象的属性上。
- 事件处理:
- 支持事件驱动模型,允许应用程序的不同部分通过事件进行通信。
- 定义了一套事件处理机制,允许 Bean 发布和监听应用中的事件。首先,定义一个事件类继承自
ApplicationEvent,然后在需要发布事件的地方通过ApplicationContext发布事件:
- 资源抽象:
- 提供了一套资源抽象机制,使得访问不同类型(如文件、类路径资源、URL资源等)的资源变得更加简单和统一。
- 外部资源访问:可以方便地加载和访问各种外部资源,如属性文件、XML 文件等。通过
ResourceLoader接口和ApplicationContext实现类,可以轻松地获取资源的输入流进行读取。例如:
- 异常处理:
- 提供了统一的异常处理机制,允许开发者捕获和处理整个应用程序范围内的异常。
- 表达式语言(SpEL):
- 提供了一个强大的表达式语言,用于在运行时查询和操作对象图。
- AOP 支持:
- 提供了对面向切面编程的支持,允许开发者将横切关注点(如日志记录、事务管理)与业务逻辑分离。
- 模块化:
- Spring Core 是高度模块化的,允许开发者根据需要选择使用特定的模块。
- 兼容性:
- 与 Java 平台标准兼容,支持 Java SE 和 Java EE。
- 集成性:
- 可以与其他 Java 技术(如 JDBC、JMS、JPA、Hibernate 等)和框架无缝集成。
- 测试支持:
- 提供了对单元测试和集成测试的支持,使得测试 Spring 应用程序变得更加容易。
- 无代码侵入性:
- 通过使用接口和注解,Spring Core 允许开发者以非侵入的方式构建应用程序。
- 可扩展性:
- 允许开发者通过自定义扩展来满足特定的需求。
1.2 代码示例:
XML文件
resources目录下的文件
<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi

最低0.47元/天 解锁文章
173万+

被折叠的 条评论
为什么被折叠?



