介绍一下@compent注解作用?
@Component 是 Spring Framework 中的一个注解,用于将类标记为 Spring 的 组件。被 @Component 注解标记的类将被 Spring 容器自动检测并作为 Bean 进行管理。它是 Spring IoC(控制反转)容器中的一种注解,用于实现依赖注入和自动装配。
主要功能
将类注册为 Spring Bean
@Component 告诉 Spring 容器该类需要作为一个 Bean,加入到容器的管理中。Spring 在启动时会扫描带有 @Component 注解的类并将其实例化为 Bean。自动扫描和装配
当你在 Spring 配置中使用 @ComponentScan 时,Spring 会扫描指定包下的所有类,自动检测使用了 @Component 注解的类,并将这些类实例化为 Bean,并将它们放入 IoC 容器中供依赖注入使用。
使用场景
@Component 常用于一般性组件的定义,它是一个通用的注解,适用于所有的 Bean 定义,通常用于标记那些没有特殊用途的类。具体的组件类型还有一些衍生的注解:
@Service:标记业务逻辑类(Service 层)。
@Repository:标记数据访问层类(DAO 层),具备将数据库访问异常转换为 Spring 的统一异常机制的功能。
@Controller:标记 Spring MVC 的控制器类(Web 层)。
这些注解都是 @Component 的衍生,它们的作用相同,只是为了语义化和便于区分各个层次的职责。
示例代码
java
@Component
public class MyComponent {
public void doSomething() {
System.out.println(“MyComponent is working”);
}
}
配合 @Autowired 实现依赖注入
@Component 通常与 @Autowired 一起使用,通过 @Autowired 将其他 Bean 自动注入到该类中。
@Component
public class MyService {
@Autowired
private MyComponent myComponent;
public void performAction() {
myComponent.doSomething();
}
}
在上面的例子中,MyComponent 被 @Component 注解标记,成为 Spring 容器中的一个 Bean。MyService 通过 @Autowired 自动注入了 MyComponent 的实例。
扫描和自动检测
为了使 @Component 生效,通常在 Spring 的配置类或启动类中使用 @ComponentScan 注解,指定 Spring 容器需要扫描的包路径,或者直接使用 Spring Boot 的自动扫描功能。
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// 配置类
}
或者在 Spring Boot 中,只要类在主启动类所在的包或子包中,Spring Boot 会自动扫描并注册带有 @Component 注解的 Bean。
总结
@Component 用于将类注册为 Spring 的 Bean,使其被 Spring 容器管理。
它是 Spring 的基础注解,适用于一般组件的定义,常与 @Autowired 搭配使用进行依赖注入。
在业务中,衍生的注解如 @Service、@Repository 和 @Controller 用于特定场景,但本质上它们都继承了 @Component 的功能。
过滤器与拦截器的应用场景有哪些?
下面是过滤器和拦截器的使用场景区别的具体例子:
过滤器的使用场景
请求日志记录:
在所有请求到达服务器之前,使用过滤器记录请求的详细信息,如 URL、请求时间、请求方法等,以便进行审计或分析。
请求和响应编码处理:
通过过滤器对请求体和响应体进行编码转换,例如将请求的字符编码设置为 UTF-8,确保应用程序能够正确处理不同编码的请求。
安全控制:
在过滤器中检查用户的身份验证信息,决定是否允许访问某些资源。如果用户未通过身份验证,则可以重定向到登录页面。
跨域请求处理:
在过滤器中添加 CORS(跨域资源共享)相关的响应头,允许前端应用从不同源请求资源。
拦截器的使用场景
权限验证:
在业务逻辑执行之前,使用拦截器检查用户是否具有访问特定控制器方法的权限,未授权的请求将被拒绝。
事务管理:
在拦截器中开启和提交数据库事务,以确保业务逻辑的原子性。如果业务处理失败,则回滚事务。
性能监控:
使用拦截器记录控制器方法的执行时间,以评估不同业务逻辑的性能,并进行性能优化。
请求参数校验:
在业务方法执行之前,使用拦截器对请求参数进行校验,确保参数符合预期格式。如果校验失败,直接返回错误响应。
总结
过滤器 更侧重于对请求和响应的全局性处理,适用于处理与请求生命周期相关的操作,如日志、编码、安全控制等。
拦截器 主要关注于特定业务逻辑的增强,适用于处理与业务相关的操作,如权限、事务、性能监控等。
简单介绍一下你对spring的理解
对 Spring 框架的理解通常涉及两个重要的概念:IoC(控制反转)和AOP(面向切面编程)。以下是对这两个概念的简单介绍:
1. IoC(控制反转)
概念:IoC 是一种设计原则,用于降低系统组件之间的耦合度。在传统的编程模式中,程序员负责控制对象的创建和管理。而在 IoC 中,控制权被反转,通常由框架来管理对象的生命周期和依赖关系。
实现方式:
依赖注入(DI):IoC 的实现方式之一是依赖注入。Spring 通过构造函数、setter 方法或字段注入的方式将依赖对象注入到目标对象中。这样,目标对象不再负责创建其依赖的对象,从而降低了耦合度。
好处:
提高了代码的可测试性,易于进行单元测试。
增强了代码的灵活性和可维护性,可以轻松替换实现类。
促进了松耦合的设计,便于系统的扩展和重用。
2. AOP(面向切面编程)
概念:AOP 是一种编程范式,它允许开发者在不修改业务逻辑的情况下,插入横切关注点(如日志、事务、安全等)到应用程序中。AOP 的主要目的是实现代码的模块化,提高代码的重用性。
核心概念:
切面(Aspect):切面是横切关注点的模块化表示,包含了横切逻辑和切入点。
切入点(Pointcut):定义了在哪些位置(方法、类等)应用切面逻辑。
通知(Advice):在切入点处执行的具体逻辑,分为前置通知、后置通知、异常通知等。
实现方式:
Spring AOP 提供了对方法的增强功能,可以在方法执行前、执行后或出现异常时插入自定义逻辑。Spring AOP 基于代理模式实现,通常通过 JDK 动态代理或 CGLIB 代理来增强目标对象。
好处:
提高了代码的可维护性,减少了代码重复。
使得业务逻辑与横切逻辑分离,便于管理和维护。
便于实现跨越多个模块的功能,如日志记录和事务管理。
总结
IoC 通过控制对象的创建和管理,使得应用程序更加灵活、可测试和可维护。
AOP 则通过将横切关注点与业务逻辑分离,提高了代码的模块化,减少了代码重复。
这两个概念是 Spring 框架的核心,帮助开发者构建高效、灵活和可维护的企业级应用。
Spring中如何实现IOC的?
Spring 实现 IoC(控制反转)主要通过 依赖注入(DI) 的方式。以下是 Spring IoC 的实现过程和机制:
1. Bean 的定义
在 Spring 中,所有的对象(即 Bean)都由 Spring IoC 容器管理。可以通过 XML 配置文件、注解或 Java 配置类来定义 Bean。
XML 配置:
<bean id="myBean" class="com.example.MyBean"> <property name="dependency" ref="myDependency"/> </bean>
Java 注解:
@Component public class MyBean { @Autowired private MyDependency dependency; }
Java 配置类:
@Configuration public class AppConfig { @Bean public MyBean myBean() { return new MyBean(myDependency()); } @Bean public MyDependency myDependency() { return new MyDependency(); } }
2. 容器的创建
Spring IoC 容器是负责管理 Bean 的核心部分。可以使用 ApplicationContext 接口或 BeanFactory 类来创建和配置 IoC 容器。
java
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
3. 依赖注入
一旦容器创建并加载了 Bean 的定义,Spring 将负责注入 Bean 的依赖。这可以通过以下几种方式实现:
构造器注入:
通过构造函数传递依赖。
public class MyBean { private final MyDependency dependency; @Autowired public MyBean(MyDependency dependency) { this.dependency = dependency; } }
Setter 注入:
通过 setter 方法设置依赖。
public class MyBean { private MyDependency dependency; @Autowired public void setDependency(MyDependency dependency) { this.dependency = dependency; } }
字段注入:
直接在字段上使用注解进行注入(不推荐,因降低了可测试性)。
public class MyBean { @Autowired private MyDependency dependency; }
4. Bean 的生命周期管理
Spring 负责管理 Bean 的生命周期,从创建到销毁。可以通过配置 init-method 和 destroy-method 或使用注解 @PostConstruct 和 @PreDestroy 来定义 Bean 的初始化和销毁逻辑。
5. 作用域
Spring 提供多种 Bean 作用域,包括单例(singleton)、原型(prototype)、请求(request)、会话(session)等。可以通过在 Bean 定义中指定作用域来控制 Bean 的生命周期。
总结
Spring 的 IoC 通过定义和管理 Bean 的方式,实现了依赖的控制和注入,从而降低了模块之间的耦合,提高了代码的可维护性和可测试性。通过使用不同的注入方式和配置方式,开发者可以灵活地构建和管理应用程序的组件。
简述一下控制反转的思想及优缺点?
控制反转的思想
控制反转(Inversion of Control,IoC) 是一种软件设计原则,旨在通过将对象的创建和管理从应用程序代码中抽象出来,降低组件之间的耦合度。其核心思想是反转了传统的控制流程,即不再由程序主动控制对象的创建和依赖关系,而是由一个外部容器或框架来管理这些对象。
核心思想
依赖注入(Dependency Injection, DI):控制反转的一种具体实现方式,通过将对象的依赖关系交给 IoC 容器来处理,从而解耦代码。
反转控制:传统上,应用程序负责对象的生命周期和依赖关系的管理,而在 IoC 中,这种控制权被转移到框架或容器。
优点
降低耦合性:
组件之间通过接口或抽象类进行交互,减少了直接依赖,提高了系统的灵活性。
提高可测试性:
由于依赖关系是由容器管理的,开发人员可以轻松地进行单元测试,替换或模拟依赖对象。
增强模块化:
系统的模块化得以增强,各模块的责任更清晰,便于维护和扩展。
简化对象管理:
IoC 容器负责对象的创建、生命周期管理和依赖关系解析,开发者可以专注于业务逻辑。
易于维护和扩展:
通过松耦合的设计,可以更方便地替换实现类或添加新功能,而不需要大量修改现有代码。
缺点
学习曲线:
对于初学者来说,理解 IoC 和 DI 的概念及其实现可能需要一定的学习成本。
性能开销:
在某些情况下,IoC 容器的动态管理可能引入一定的性能开销,尤其是在需要大量创建和销毁对象时。
调试困难:
由于对象的创建和管理是由容器控制的,跟踪依赖关系可能变得复杂,调试时可能会遇到困难。
过度设计:
在简单应用中,使用 IoC 容器可能导致过度设计,增加了不必要的复杂性。
总结
控制反转是一种强大的设计原则,能够提升代码的灵活性、可维护性和可测试性,但在应用时也需要权衡其复杂性和性能开销。适当的场景下应用 IoC 能够大大增强系统的设计质量。
Spring框架中用到了哪些设计模式,作用是什么?
Spring框架中用到了多种设计模式,以下是一些主要的设计模式:
一、单例模式(Singleton Pattern)
在Spring中的体现
Spring框架中的Bean默认是单例模式。例如,当在Spring容器中配置一个数据源(DataSource)Bean时,整个应用程序通常只需要一个数据源实例。Spring通过管理Bean的生命周期,确保在容器中对于特定的Bean定义,只会创建一个实例,并在整个应用程序中共享这个实例。
这种单例模式的实现有助于减少内存开销,因为不需要为每个使用数据源的地方都创建一个新的实例。同时,也便于集中管理资源,如数据库连接池的管理等。
二、工厂模式(Factory Pattern)
Bean工厂(BeanFactory)
BeanFactory是Spring框架中的一个核心接口,它是实现工厂模式的重要体现。BeanFactory负责创建和管理Bean对象。例如,当应用程序从Spring容器中获取一个Bean时,实际上是由BeanFactory根据Bean的定义(配置信息)来创建这个Bean的实例。
它可以根据不同的配置(如XML配置或者基于注解的配置)来实例化不同类型的Bean,就像一个工厂根据不同的订单生产不同的产品一样。
ApplicationContext作为工厂的扩展
ApplicationContext是BeanFactory的子接口,它在BeanFactory的基础上提供了更多的功能,如国际化支持、事件传播等。但从本质上讲,它也是一种工厂,用于创建和管理Bean实例。
三、代理模式(Proxy Pattern)
AOP(Aspect - Oriented Programming)中的代理
在Spring的AOP实现中广泛使用了代理模式。例如,当为一个业务对象添加事务管理或者日志记录等横切面功能时,Spring会创建一个代理对象。这个代理对象会在调用目标业务对象的方法前后执行额外的逻辑(如开启和提交事务,或者记录方法调用的日志)。
如果目标对象实现了接口,Spring可能会使用JDK动态代理来创建代理对象;如果目标对象没有实现接口,Spring会使用CGLIB代理来创建代理对象。
四、模板模式(Template Pattern)
JdbcTemplate等模板类
Spring中的JdbcTemplate是模板模式的一个典型应用。JdbcTemplate提供了一个执行数据库操作的模板框架,它定义了执行数据库查询、更新等操作的基本流程。例如,在执行一个数据库查询操作时,JdbcTemplate已经定义好了获取数据库连接、创建语句对象、执行查询、处理结果集以及关闭资源等基本步骤。
开发人员只需要实现其中特定的部分,如提供SQL语句和结果集映射逻辑等,就可以方便地进行数据库操作。这种方式避免了开发人员每次都要重复编写数据库操作的基本流程代码,提高了代码的复用性和开发效率。
五、观察者模式(Observer Pattern)
事件机制(Application Event)
Spring的事件机制是观察者模式的体现。例如,当一个特定的事件(如应用程序启动完成事件)发生时,相关的监听器(观察者)会得到通知并执行相应的操作。
一个组件(事件源)可以发布事件,而多个监听器可以订阅这些事件。当事件源发布一个事件时,所有订阅了该事件的监听器都会被调用,从而实现了一种松耦合的事件通知和处理机制。
Springboot有哪些优点?
1、 减少开发,测试时间和努力。
2、 使用JavaConfig有助于避免使用XML。
3、 避免大量的Maven导入和各种版本冲突。
4、 提供意见发展方法。
5、 通过提供默认值快速开始开发。
6、 没有单独的Web服务器需要。这意味着你不再需要启动Tomcat,Glassfish或其他任何东西。
7、 需要更少的配置 因为没有web.xml文件。只需添加用@ Configuration注释的类,然后添加用@Bean注释的方法,Spring将自动加载对象并像以前一样对其进行管理。您甚至可以将@Autowired添加到bean方法中,以使Spring自动装入需要的依赖关系中。
8、 基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:-Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,Spring将在(application{environment} .properties)中加载后续的应用程序属性文件。
项目中为什么使用SpringBoot?
在项目中使用 Spring Boot 有以下几个主要原因:
一、快速开发
简化配置:
Spring Boot 极大地简化了传统 Spring 应用的配置过程。它通过自动配置机制,根据项目中引入的依赖自动配置相应的组件,减少了大量繁琐的 XML 配置文件。
例如,当引入 Spring Data JPA 依赖时,Spring Boot 会自动配置数据库连接和 JPA 相关的组件,无需手动配置数据源、实体管理器等。
起步依赖:
通过起步依赖(starter dependencies),可以轻松地引入一系列相关的技术栈。只需在项目的构建文件中添加一个起步依赖,就可以自动引入该技术所需的所有依赖库。
比如,添加 spring-boot-starter-web 依赖,就可以快速搭建一个 Web 应用,包括 Spring MVC、Tomcat 等组件都会自动被引入和配置。
内置服务器:
Spring Boot 内置了 Tomcat、Jetty 等服务器,无需额外部署应用服务器,直接运行项目即可启动服务器,极大地提高了开发效率。
开发人员可以专注于业务逻辑的开发,而不必花费时间在服务器的配置和部署上。
二、微服务架构支持
独立部署:
Spring Boot 应用可以独立打包成可执行的 JAR 包或 WAR 包,每个应用都可以独立部署和运行。这使得微服务架构中的各个服务可以独立开发、测试和部署,提高了开发的灵活性和可维护性。
例如,一个电商系统可以拆分为订单服务、商品服务、用户服务等多个微服务,每个服务都可以用 Spring Boot 开发并独立部署。
轻量级:
Spring Boot 应用相对轻量级,启动速度快,占用资源少。这对于微服务架构中的大量服务非常重要,可以快速启动和运行各个服务,提高系统的整体性能。
服务发现和注册:
可以方便地与服务发现和注册组件(如 Eureka、Consul 等)集成,实现微服务的自动注册和发现。这使得各个微服务可以动态地找到彼此,提高了系统的可扩展性和灵活性。
三、生产就绪特性
监控和管理:
Spring Boot 提供了 Actuator 模块,可以对应用进行监控和管理。通过 Actuator 暴露的端点,可以获取应用的运行状态、性能指标、健康状况等信息,方便进行生产环境的监控和故障排查。
例如,可以查看应用的内存使用情况、数据库连接数、请求处理时间等指标,及时发现和解决性能问题。
安全集成:
易于集成 Spring Security 等安全框架,提供安全的应用环境。可以实现用户认证、授权、加密等安全功能,保护应用的数据和资源。
对于企业级应用,安全是至关重要的,Spring Boot 的安全集成可以快速为应用添加安全防护。
错误处理:
提供了统一的错误处理机制,可以对应用中的异常进行优雅的处理和展示。当应用出现错误时,可以返回友好的错误信息给用户,提高用户体验。
同时,也方便开发人员进行错误排查和调试。
四、社区活跃和生态丰富
大量的插件和扩展:
Spring Boot 拥有庞大的社区和丰富的生态系统,有大量的插件和扩展可供选择。可以根据项目的需求轻松引入各种功能模块,如缓存、消息队列、定时任务等。
例如,引入 Spring Boot Starter Cache 依赖可以方便地使用缓存功能,引入 Spring Boot Starter Quartz 可以实现定时任务调度。
技术更新快:
Spring 社区非常活跃,不断推出新的版本和功能。Spring Boot 也会及时跟进,保持技术的先进性和稳定性。这使得开发人员可以使用最新的技术来构建应用,提高应用的性能和功能。
学习资源丰富:
由于 Spring Boot 的广泛使用,有大量的学习资源可供参考,包括官方文档、教程、博客、论坛等。这使得开发人员可以快速学习和掌握 Spring Boot 的使用方法,提高开发效率。
Spring Boot Starters是什么?
Spring Boot Starters 是 Spring Boot 提供的一系列预定义的 Maven 依赖包(或 Gradle 依赖),用于帮助开发者快速集成常见的库和框架,并减少项目中手动配置的工作量。每个 Starter 包含了一组相关的依赖,方便开发者以简化的方式引入常见的功能,如 Web、数据访问、安全等。
Spring Boot Starters 的作用
简化依赖管理:通过引入一个 Starter,你可以一次性引入一组相关的依赖,而不需要手动列出每个依赖的具体版本和配置。
提供自动配置:Starters 通常会与 Spring Boot 的自动配置功能结合,自动配置常用的框架和工具。开发者只需添加依赖,并在配置中进行少量设置,Spring Boot 就会自动完成相关的初始化工作。
减少配置冲突:Spring Boot 管理了 Starter 中的依赖版本,确保这些依赖之间的兼容性,减少手动配置依赖时可能遇到的版本冲突问题。
常见的 Spring Boot Starters
Spring Boot 提供了多种常用的 Starter,覆盖了绝大部分的开发需求。以下是一些常见的 Spring Boot Starters:
spring-boot-starter
:基础的 Starter,提供了 Spring 框架的核心功能,包括依赖注入和 AOP。spring-boot-starter-web
:用于构建 Web 应用,包含 Spring MVC 和嵌入式的 Tomcat 容器。spring-boot-starter-data-jpa
:用于集成 Spring Data JPA 和 Hibernate,以便实现关系数据库的持久化操作。spring-boot-starter-security
:用于集成 Spring Security 以实现身份验证和授权功能。spring-boot-starter-test
:包含 JUnit、Mockito 等测试库,用于集成测试和单元测试。spring-boot-starter-thymeleaf
:用于集成 Thymeleaf 模板引擎,方便构建基于 HTML 的视图层。spring-boot-starter-actuator
:用于添加应用的监控和管理功能,提供运行时指标、健康检查、环境信息等功能。
如何使用 Spring Boot Starters
在 Maven 或 Gradle 项目中,使用 Spring Boot Starters 非常简单。以 Maven 为例,你只需要在 pom.xml
文件中添加对应的依赖,例如:
<dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot JPA Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
总结
Spring Boot Starters 通过整合常见功能的依赖库和简化配置,使得开发者能够更快、更高效地构建应用程序,降低项目启动的复杂性。
过滤器和拦截器的区别?
解释一下 Spring AOP 里面的几个名词?
AOP(Aspect - Oriented Programming)
定义:面向切面编程,是一种编程范式,它允许开发者将横切关注点(如日志记录、事务管理、安全检查等)从业务逻辑中分离出来,以提高代码的模块化和可维护性。与传统的面向对象编程(OOP)不同,OOP主要侧重于将问题分解为对象和它们之间的交互,而AOP侧重于处理跨越多个对象的功能。
示例:在一个企业级应用中,有多个业务模块,如用户管理模块、订单管理模块、产品管理模块等。每个模块都可能需要记录操作日志。如果没有AOP,就需要在每个模块的每个方法中添加日志记录代码。使用AOP后,可以将日志记录这个横切关注点提取出来,统一进行处理,这样当需要修改日志记录的方式时,只需要在一个地方修改即可。
Aspect(切面)
定义:切面是对横切关注点的模块化抽象,它包含了横切逻辑(如通知)以及连接点(Join Point)的定义。可以把它看作是一个包含了一系列要应用到目标对象方法上的代码块的集合。
示例:一个日志记录切面可能包含了在方法执行前记录方法开始时间、在方法执行后记录方法结束时间和结果的逻辑。这个切面会被应用到多个需要记录日志的业务方法上。
Join Point(连接点)
定义:在程序执行过程中能够插入切面的点。在Spring AOP中,连接点通常是指方法的调用或者方法的执行。这些点是AOP框架可以“挂钩”的地方,用于应用通知(Advice)。
示例:在一个Java类中有多个方法,每个方法的调用处就是一个连接点。比如,在一个用户服务类中有
addUser()
、updateUser()
和deleteUser()
方法,这些方法的调用时刻都是连接点。
Advice(通知)
定义:通知定义了切面在特定连接点要执行的操作。它是切面的具体行为部分,包括在连接点之前(Before)执行的前置通知、在连接点之后(After)执行的后置通知、在连接点返回结果后(After - Returning)执行的返回通知、在连接点抛出异常后(After - Throwing)执行的异常通知,以及环绕(Around)连接点执行的环绕通知。
示例:
前置通知:在执行数据库查询操作之前,打开数据库连接。
后置通知:在执行完业务方法后,关闭数据库连接,无论方法是否抛出异常。
返回通知:当一个查询用户信息的方法成功返回用户对象后,对返回的用户对象进行一些数据加密操作。
异常通知:如果在执行支付方法时出现异常,记录异常信息并进行一些回滚操作。
环绕通知:在执行一个复杂的业务逻辑方法时,先进行权限检查,然后执行方法本身,最后记录方法的执行时间。
Pointcut(切点)
定义:切点用于定义哪些连接点会被切面应用通知。它是一个表达式或者一组规则,用来匹配连接点。通过切点,AOP框架可以准确地找到需要应用切面逻辑的方法。
示例:可以使用表达式“execution(* com.example.service..(…))”作为切点。这个表达式表示匹配“com.example.service”包下的所有类的所有方法。这样,定义的切面(如日志记录切面)就会应用到这些匹配的方法上。
Proxy(代理)
定义:在Spring AOP中,代理是AOP实现的一种机制。当一个目标对象被切面环绕时,Spring会创建一个代理对象来代替原始对象。代理对象负责在适当的连接点调用通知和目标对象的方法。有两种类型的代理:JDK动态代理和CGLIB代理。JDK动态代理是基于接口的代理,要求目标对象实现接口;CGLIB代理是基于类的代理,可以代理没有实现接口的类。
示例:假设存在一个实现了接口
UserService
的UserServiceImpl
类。当应用AOP来对UserServiceImpl
进行日志记录时,Spring会创建一个JDK动态代理对象(如果UserServiceImpl
实现了接口)。这个代理对象会拦截对UserServiceImpl
方法的调用,先执行日志记录通知,然后再调用UserServiceImpl
的实际方法。如果UserServiceImpl
没有实现接口,Spring会使用CGLIB代理来实现类似的功能。
Weaving(织入)
定义:织入是将切面应用到目标对象并创建代理对象的过程。它将切面的通知与目标对象的连接点结合起来,使得在运行时能够按照定义的规则执行横切逻辑。织入可以在编译时、类加载时或者运行时进行。Spring AOP主要是在运行时进行织入。
示例:在一个基于Spring的Web应用启动过程中,当Spring容器初始化时,会对标记了要应用AOP的Bean进行织入操作。例如,对于一个被配置为需要进行事务管理切面的业务服务Bean,Spring会在运行时将事务管理的通知织入到该Bean的方法调用过程中,使得在执行这些方法时能够自动开启、提交或者回滚事务。