Java 学习笔记(四)

@Scope

@Scope 是 Spring 框架中的一个注解,用于指定一个 bean 的作用域。在 Spring 应用程序中,bean 的作用域决定了它的生命周期和可见性。通过 @Scope 注解,你可以精确地控制 bean 的行为,以确保它在需要时存在,并在不再需要时被正确地清理。

@Scope 注解可以应用于类级别或方法级别(在使用 @Bean 注解的方法上)。它通常与 @Component、@Service、@Repository 或 @Bean 等注解一起使用,以指示 Spring 容器如何管理该 bean 的实例。

@Scope 的参数
@Scope 注解有一个主要的参数 scopeName,它指定了 bean 的作用域。Spring 提供了几种预定义的作用域,同时也允许你通过实现 Scope 接口来定义自定义作用域。

singleton(默认):每个 Spring IoC 容器中仅有一个 bean 实例,该实例被所有对该 bean 的引用共享。
prototype:每次请求 bean 时都会创建一个新的实例。
request:在 web 应用中,bean 定义在请求的范围内。即每个 HTTP 请求都会创建一个新的 bean 实例,且该实例仅在当前请求中有效。
session:在 web 应用中,bean 定义在会话的范围内。即每个 HTTP 会话都会创建一个新的 bean 实例,且该实例在该会话中共享。
application:在 web 应用中,bean 定义在 ServletContext 的范围内。即每个 web 应用仅有一个 bean 实例,该实例被所有用户共享。
websocket:在 web 应用中,bean 定义在 WebSocket 的范围内。这是 Spring 4.0 中引入的,用于支持 WebSocket 协议的 bean 作用域。
使用示例

import org.springframework.context.annotation.Scope;  
import org.springframework.stereotype.Component;  
  
@Component  
@Scope("prototype")  
public class MyPrototypeBean {  
    // 类定义  
}  
  
// 或者在配置类中定义  
  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.context.annotation.Scope;  
  
@Configuration  
public class AppConfig {  
  
    @Bean  
    @Scope("request")  
    public MyRequestBean myRequestBean() {  
        return new MyRequestBean();  
    }  
}

在上述示例中,MyPrototypeBean 被声明为原型作用域,这意味着每次从 Spring 容器中请求它时,都会获得一个新的实例。而 myRequestBean 方法定义的 bean 被声明为请求作用域,仅在当前 HTTP 请求期间有效。

自定义作用域
如果你需要定义一个自定义的作用域,你需要实现 Scope 接口并注册一个 CustomScopeConfigurer bean 来告知 Spring 关于你的新作用域。这通常涉及更复杂的配置,适用于特定的用例,如集群环境中的会话管理等。

@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true)

@ConditionalOnProperty 是 Spring Boot 提供的一个条件注解,用于根据应用程序中的配置属性(即 application.properties 或 application.yml 文件中的配置)来决定某个配置类、Bean 或自动配置类是否应该被包含进最终的 Spring 应用上下文中。这对于条件化地激活或禁用自动配置特别有用。

下面是 @ConditionalOnProperty 注解的详细参数解释,包括你提到的那个具体示例:

prefix: 指定配置属性的前缀。在你的例子中,prefix = "spring.aop" 表示我们将关注 spring.aop 开头的配置属性。
name: 指定配置属性的名称。在你的例子中,name = "auto" 表示我们将特别关注 spring.aop.auto 这个配置属性。
havingValue: 指定期望的配置属性值。在你的例子中,havingValue = "true" 表示只有当 spring.aop.auto 的值等于 true 时,
条件才成立。
matchIfMissing: 当指定的配置属性不存在时,是否认为条件成立。在你的例子中,
matchIfMissing = true 表示如果 spring.aop.auto 配置没有指定(即不存在这个配置项),则条件也被视为成立。
这常用于提供一个默认值或行为,如果配置未被明确指定。

综合上述参数,@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true) 注解的含义是:如果 spring.aop.auto 的配置值为 true,或者该配置项完全不存在(因为 matchIfMissing = true),则条件成立,标注了该注解的类、方法或Bean将被包含进Spring应用上下文中。

这种机制对于创建可选功能特别有用,尤其是当你想让用户通过简单的配置来启用或禁用某个功能时。通过使用 @ConditionalOnProperty,你可以非常灵活地控制哪些配置和Bean被包含在你的应用中,使得你的应用更加模块化和可配置。

SPI 机制

SPI(Service Provider Interface)机制是Java平台的一种服务提供者机制,它允许第三方为Java核心库或框架提供自定义的实现。这种机制通过基于接口的编程、策略模式以及配置文件的方式,实现了动态加载和替换组件的功能,从而增强了系统的可扩展性和灵活性。下面将详细介绍SPI机制在Java和SpringBoot中的使用,并给出示例代码。

SPI机制概述
SPI机制的核心思想在于解耦服务提供者和使用者,通过接口定义服务规范,而具体的实现则由不同的服务提供者提供。Java平台通过java.util.ServiceLoader类来加载和发现这些服务提供者。服务提供者需要在其jar包的META-INF/services目录下创建一个以接口全限定名命名的文件,文件内容为实现该接口的具体类的全限定名。

SPI在Java中的使用
在Java中,SPI机制主要用于扩展Java平台的能力,比如JDBC(Java Database Connectivity)通过SPI机制加载不同数据库的驱动,SLF4J(Simple Logging Facade for Java)通过SPI机制加载不同日志框架的实现等。

示例代码
以下是一个简单的Java SPI使用示例:

定义服务接口

public interface Log {  
    void log(String message);  
}

创建服务实现类

public class ConsoleLogger implements Log {  
    @Override  
    public void log(String message) {  
        System.out.println("Console Logger: " + message);  
    }  
}  
 
public class FileLogger implements Log {  
    @Override  
    public void log(String message) {  
        System.out.println("File Logger: " + message);  
    }  
}

创建配置文件

在src/main/resources/META-INF/services目录下创建名为com.example.Log的文件(假设Log接口的全限定名为com.example.Log),文件内容如下:

com.example.ConsoleLogger  
com.example.FileLogger

加载服务实现类

import java.util.ServiceLoader;  
 
public class App {  
    public static void main(String[] args) {  
        ServiceLoader<Log> serviceLoader = ServiceLoader.load(Log.class);  
        for (Log log : serviceLoader) {  
            log.log("Hello SPI");  
        }  
    }  
}

这段代码会输出:

Console Logger: Hello SPI  
File Logger: Hello SPI

SPI在SpringBoot中的使用
在SpringBoot中,SPI机制同样被广泛应用,主要用于自动注册各种组件,如自动注册插件、自动注册事件监听器、自动注册过滤器等。SpringBoot通过spring.factories文件(位于META-INF目录下)来配置SPI机制,该文件包含了SpringBoot运行时需要读取的类信息。

示例(概念性说明)
虽然SpringBoot中的SPI使用更多是通过spring.factories文件配置的,而不是直接通过ServiceLoader类加载,但背后的思想是一致的:通过接口定义服务,并通过配置文件指定实现类。SpringBoot在启动时会自动扫描spring.factories文件,并加载其中指定的类。

例如,在spring.factories文件中配置一个自定义的ApplicationListener:

org.springframework.context.ApplicationListener=com.example.MyApplicationListener

这样,SpringBoot在启动时就会自动加载并注册com.example.MyApplicationListener作为ApplicationListener的实现。

总结
SPI机制是Java平台提供的一种强大的服务提供者机制,它通过接口定义服务规范,允许第三方提供具体的实现,并通过配置文件和ServiceLoader类实现动态加载和替换。在Java和SpringBoot中,SPI机制都得到了广泛的应用,为系统的扩展性和灵活性提供了有力的支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上阡陌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值