Spring的反转控制你真的明白了吗?(上)

简介: Spring的反转控制你真的明白了吗?

IoC(控制反转)和 DI(依赖注入)


IoC 是 Spring 的核心理念之一,也是 Spring 最为著名的特性之一。它将对象的创建、管理和销毁等过程交给 Spring 容器来完成。DI 则是 IoC 的具体实现,它通过注入依赖对象的方式来完成对象之间的解耦。

IoC(控制反转)是一种设计模式,它将对象的创建、管理和销毁等过程交给容器来完成,而不是由代码显式地进行。这样可以降低代码的耦合度和复杂度,并且提高代码的可测试性和可维护性。

DI(依赖注入)是 IoC 的具体实现方式之一,它通过注入依赖对象的方式来完成对象之间的解耦。在 Spring 中,我们可以通过构造方法注入、setter 方法注入和字段注入等方式实现依赖注入。

下面是一些常见的 IoC 和 DI 相关的概念:


Bean’


Bean 是一个由 Spring 容器管理的对象。在 Spring 中,我们可以将 Java 类声明为一个 Bean,并由容器来创建、初始化和销毁它。


ApplicationContext


ApplicationContext 是 Spring 提供的一个接口,它是 IoC 容器的核心接口。ApplicationContext 在初始化时会创建 Bean 实例,并管理它们的生命周期。


BeanFactory


BeanFactory 是 ApplicationContext 的父接口,它也是 Spring 容器的核心接口。BeanFactory 只负责管理 Bean 实例的生命周期,而不会主动地创建 Bean 实例。


配置文件


Spring 中的配置文件通常使用 XML 格式,用于描述应用程序中的 Bean、Bean 之间的依赖关系、以及其他相关的配置信息。

现在我们来看一下如何在 Java 代码中实现 IoC 和 DI。


1. 声明 Bean


我们可以使用 @Component、@Service、@Controller、@Repository 等注解来将一个 Java 类声明为一个 Bean。这些注解都是 @Component 的派生注解,它们的作用是告诉 Spring 容器,这个类需要被管理。


例如:

@Service
public class UserService {
    // ...
}


2. 使用 ApplicationContext


下面是一个简单的使用 ApplicationContext 的例子,其中通过 getBean() 方法获得了 UserService 实例:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean(UserService.class);


3. 依赖注入


我们可以使用 @Autowired 注解、构造方法注入或 setter 方法注入等方式来实现依赖注入。


例如:

@Service
public class UserService {
    private UserDao userDao;
    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
    // 或者使用 setter 方法注入
    // @Autowired
    // public void setUserDao(UserDao userDao) {
    //     this.userDao = userDao;
    // }
}


通过上述代码,Spring 在创建 UserService 对象时会自动注入一个 UserDao 实例,从而实现了对象之间的解耦。


AOP(面向切面编程)


AOP 是 Spring 的另一个核心特性,它可以在不修改原有代码的情况下,通过切入点和通知等机制,动态地添加或移除一些功能模块,比如日志记录、安全检查等。

AOP(面向切面编程)是一种编程范式,它可以在不修改原有代码的情况下,通过动态地横向切入程序执行流程中的某些特定点,往程序中添加或删除业务逻辑。AOP 通过将横切关注点与正常的业务逻辑分离来提高代码的可维护性和可扩展性。


Spring AOP 是基于代理模式实现的,它通过拦截器来实现对方法的增强。在 Spring 中,我们可以通过配置切面、切入点和通知等机制来实现 AOP。


下面是一些常见的 AOP 相关的概念:


Join Point


Join Point 是指在程序执行过程中的某个特定点,比如方法调用、异常处理等。


Pointcut


Pointcut 是指一个表达式,它定义了哪些 Join Point 应该被拦截。比如可以使用表达式 execution(* com.example….(…)) 来匹配 com.example 包及其子包下的所有方法。


Advice


Advice 是指在拦截到 Join Point 后要执行的逻辑,也就是增强的具体实现方式。Spring 提供了四种类型的 Advice,分别是 Before、After、Around 和 AfterReturning。


Aspect


Aspect 是指一个横切关注点,它可以是一个类或者一个注解。Aspect 定义了 Pointcut 和 Advice,用于描述哪些 Join Point 需要被拦截以及拦截后需要执行的逻辑。


现在我们来看一下如何在 Java 代码中实现 AOP。


1. 声明切面


我们可以使用 @Aspect 注解将一个类声明为切面。在切面中,通常会定义多个 Pointcut 和对应的 Advice。


例如:

@Aspect
@Component
public class LogAspect {
    // 定义一个 Pointcut,匹配所有 UserService 的方法
    @Pointcut("execution(* com.example.service.UserService.*(..))")
    public void userServicePointcut() {}
    // Before Advice,在 UserService 方法执行前输出日志
    @Before("userServicePointcut()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("before " + joinPoint.getSignature().getName());
    }
}


2. 在配置文件中启用 AOP


我们需要在 Spring 配置文件中启用 AOP,并将切面添加到容器中。


例如:

<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.example"/>
<bean id="logAspect" class="com.example.aspect.LogAspect"/>


3. 测试


最后,我们可以编写一个测试类来验证 AOP 是否生效。


例如:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:applicationContext.xml"})
public class UserServiceTest {
    @Autowired
    private UserService userService;
    @Test
    public void test() {
        userService.addUser(new User());
        userService.deleteUser(123);
    }
}


通过上述代码,我们可以看到在 UserService 的方法执行前会输出日志,这就是 AOP 在工作。


以上就是 AOP 的一些基本概念和 Java 代码实现。需要注意的是,Spring 还有很多高级特性和用法,需要深入学习才能掌握。

相关文章
|
XML Java 数据格式
一文讲透Spring的IOC反转控制
一文讲透Spring的IOC反转控制
87 0
|
SQL 设计模式 开发框架
Spring的反转控制你真的明白了吗?(下)
Spring的反转控制你真的明白了吗?
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
1月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
161 2
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
6天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
18 2
 SpringBoot入门(7)- 配置热部署devtools工具
|
2天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
11 2
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
52 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
4月前
|
Java 测试技术 数据库
Spring Boot中的项目属性配置
本节课主要讲解了 Spring Boot 中如何在业务代码中读取相关配置,包括单一配置和多个配置项,在微服务中,这种情况非常常见,往往会有很多其他微服务需要调用,所以封装一个配置类来接收这些配置是个很好的处理方式。除此之外,例如数据库相关的连接参数等等,也可以放到一个配置类中,其他遇到类似的场景,都可以这么处理。最后介绍了开发环境和生产环境配置的快速切换方式,省去了项目部署时,诸多配置信息的修改。
|
1月前
|
XML Java 应用服务中间件
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
157 2