四时宝库

程序员的知识宝库

Spring 常用的23种扩展接口,每个接口都大有作用!看完你就懂了

Spring 框架不仅仅提供了 IOC 容器和 AOP 功能,还设计了一套灵活的扩展接口,方便开发者在应用初始化、销毁等不同阶段插入自定义逻辑。今天,我们来一起看看 Spring 中常见的扩展接口,并通过实例说明各自的使用场景!

一、InitializingBean 和 DisposableBean

  • InitializingBean:实现该接口的 Bean 会在属性填充后自动调用 afterPropertiesSet 方法,适合用来执行 Bean 的初始化逻辑。
  • DisposableBean:实现该接口的 Bean 会在容器销毁时自动调用 destroy 方法,用于清理资源。

示例

public class MyService implements InitializingBean, DisposableBean {
    @Override
    public void afterPropertiesSet() {
        System.out.println("MyService initialized");
    }

    @Override
    public void destroy() {
        System.out.println("MyService destroyed");
    }
}

使用这些接口,可以确保在 Bean 初始化和销毁时执行特定的操作,适合有启动和清理需求的服务类。

二、ApplicationContextAware 和 BeanNameAware

  • ApplicationContextAware:实现该接口的 Bean 可以在初始化时获取 ApplicationContext,让 Bean 可以直接访问 Spring 容器。
  • BeanNameAware:实现该接口的 Bean 可以获取自身在容器中的名称(即 Bean 名称),适合需要根据名称执行特定逻辑的 Bean。

示例

public class MyService implements ApplicationContextAware, BeanNameAware {
    private ApplicationContext applicationContext;
    private String beanName;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public void printInfo() {
        System.out.println("Bean name: " + beanName);
        System.out.println("Application context: " + applicationContext);
    }
}

在需要访问容器资源的场景中(如动态加载其他 Bean),这些接口特别有用。

三、BeanPostProcessor 和 BeanFactoryPostProcessor

  • BeanPostProcessor:该接口用于在 Bean 初始化前后执行自定义逻辑,是处理 Bean 属性或增强功能的常用扩展接口。
  • BeanFactoryPostProcessor:在 BeanFactory 实例化后但 Bean 实例化之前被调用,用于修改 Bean 定义,比如动态改变属性配置。

示例

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("Before Initialization of bean: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("After Initialization of bean: " + beanName);
        return bean;
    }
}

使用 BeanPostProcessor 可以实现自定义的 AOP 切面逻辑,适合日志记录、性能监控等需求。

四、ApplicationListener 和事件机制

  • ApplicationListener:Spring 的事件驱动模型中,ApplicationListener 接口用于监听容器中的事件,常用于处理应用启动、关闭等事件。

示例

@Component
public class MyEventListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("Application context refreshed!");
    }
}

这种事件机制在需要响应容器变化的场景中非常有用,例如在应用启动完成后执行某些初始化操作。

当然,Spring 中的扩展接口远不止这些,以下还有些其他常用的扩展接口,每个接口都有其独特的应用场景:

六、SmartInitializingSingleton

SmartInitializingSingleton 接口用于在所有单例 Bean 初始化完成后执行特定逻辑。通常用于依赖于其他单例 Bean 的初始化顺序较低的情况。

使用场景:比如,需要在所有单例初始化后,进行某种全局性的检查或触发。

示例

@Component
public class MySmartSingletonBean implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("All singletons have been instantiated!");
    }
}

七、EnvironmentAware

EnvironmentAware 接口允许获取 Spring 环境配置 (Environment),可以用来访问系统属性、配置文件等。

使用场景:当需要读取配置文件中的特定属性或系统属性时,非常有用。

示例

@Component
public class EnvironmentAwareBean implements EnvironmentAware {
    private Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
        String profile = environment.getActiveProfiles()[0];
        System.out.println("Active Profile: " + profile);
    }
}

八、Ordered 接口与优先级管理

Ordered 接口用于定义 Bean 的执行顺序,可以让某些特定 Bean 在其他 Bean 前优先执行。Ordered 通常结合 @Order 注解来定义顺序。

使用场景:常用于自定义的 BeanPostProcessor 或者 ApplicationListener,确保它们按照预定义顺序执行。

示例

@Component
@Order(1)
public class FirstProcessor implements Ordered {
    // 处理逻辑
    @Override
    public int getOrder() {
        return 1;
    }
}

九、ServletContextAware

ServletContextAware 接口允许获取 ServletContext,从而可以操作 Web 应用的上下文。

使用场景:适用于 Web 项目,通常用于在 Bean 中访问 Web 容器的上下文参数、资源等。

示例

@Component
public class ServletContextAwareBean implements ServletContextAware {
    @Override
    public void setServletContext(ServletContext servletContext) {
        System.out.println("ServletContext Name: " + servletContext.getServletContextName());
    }
}

十、ApplicationRunner 和 CommandLineRunner

ApplicationRunnerCommandLineRunner 是 Spring Boot 提供的两个接口,在 Spring Boot 应用启动完成后会被自动调用。

  • ApplicationRunner:可接收 ApplicationArguments 对象,适合处理应用启动参数。
  • CommandLineRunner:可接收原始的命令行参数。

使用场景:适合在应用启动时初始化数据、启动任务、打印启动信息等。

示例

@Component
public class MyAppRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        System.out.println("Application started with args: " + args.getOptionNames());
    }
}

@Component
public class MyCommandRunner implements CommandLineRunner {
    @Override
    public void run(String... args) {
        System.out.println("Command line args: " + Arrays.toString(args));
    }
}

十一、FactoryBean 接口

FactoryBean 是一个特殊的 Bean,可以自定义创建对象的过程。实现该接口的 Bean 会返回一个代理对象,而不是 Bean 本身。

使用场景:适用于需要动态生成 Bean 实例,或代理创建复杂对象的场景。

示例

public class MyFactoryBean implements FactoryBean<MyService> {
    @Override
    public MyService getObject() {
        return new MyService();
    }

    @Override
    public Class<?> getObjectType() {
        return MyService.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}


除了上面这些,Spring 的扩展接口还有一些其他常见的,继续如下所示:

十三、MessageSourceAware

MessageSourceAware 接口用于获取 MessageSource,这是 Spring 提供的国际化消息源。实现该接口的 Bean 可以访问国际化的消息,方便在应用中实现多语言支持。

使用场景:适用于需要动态获取不同语言的文本信息,常用于国际化应用中。

示例

@Component
public class MessageSourceAwareBean implements MessageSourceAware {
    private MessageSource messageSource;

    @Override
    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    public void printMessage() {
        String message = messageSource.getMessage("greeting", null, Locale.ENGLISH);
        System.out.println(message);
    }
}

十四、ResourceLoaderAware

ResourceLoaderAware 接口允许获取 ResourceLoader,可以用来加载各种类型的资源文件(如文件系统、类路径、URL)。

使用场景:当需要动态加载文件资源(如配置文件、图像等)时,可以通过该接口直接获取资源。

示例

@Component
public class ResourceLoaderAwareBean implements ResourceLoaderAware {
    private ResourceLoader resourceLoader;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public void loadResource(String path) {
        Resource resource = resourceLoader.getResource(path);
        System.out.println("Resource exists: " + resource.exists());
    }
}

十五、PropertySourcesPlaceholderConfigurer

PropertySourcesPlaceholderConfigurer 是一个用于处理属性占位符(如 ${...})的特殊 Bean,通常配合 @Value 注解使用,来从外部属性文件中加载配置。

使用场景:在项目中使用外部配置文件(如 .properties.yml 文件)时,通过该 Bean 可以在 Spring 环境中加载和解析这些配置。

示例

@Configuration
public class AppConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

十六、AsyncConfigurer

AsyncConfigurer 接口允许自定义异步任务执行器和异常处理器。通过实现该接口,可以定义自己的 ExecutorAsyncUncaughtExceptionHandler

使用场景:适用于需要自定义异步任务的执行逻辑或处理异步异常的场景。

示例

@Configuration
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        return Executors.newFixedThreadPool(5);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> System.out.println("Async error in method: " + method.getName());
    }
}

十七、EmbeddedValueResolverAware

EmbeddedValueResolverAware 接口允许获取 StringValueResolver,可以用于解析字符串中的占位符(如 ${...})和表达式(如 #{...})。

使用场景:当 Bean 中有需要动态解析的属性占位符或表达式时,通过该接口可以方便地实现解析。

示例

@Component
public class ValueResolverAwareBean implements EmbeddedValueResolverAware {
    private StringValueResolver resolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
    }

    public void printResolvedValue(String placeholder) {
        System.out.println("Resolved value: " + resolver.resolveStringValue(placeholder));
    }
}

十八、ApplicationEventPublisherAware

ApplicationEventPublisherAware 接口允许获取 ApplicationEventPublisher,可以用于在 Spring 应用上下文中发布事件。

使用场景:适用于需要在应用中触发自定义事件的情况,如某操作完成后通知其他 Bean。

示例

@Component
public class EventPublisherBean implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher eventPublisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void publishEvent(String message) {
        eventPublisher.publishEvent(new CustomEvent(this, message));
    }
}

public class CustomEvent extends ApplicationEvent {
    private String message;
    
    public CustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

十九、SmartLifecycle

SmartLifecycle 接口用于控制 Bean 的启动和停止顺序,是 Lifecycle 接口的扩展。实现该接口的 Bean 可以通过 isAutoStartup 来决定是否在容器启动时自动启动。

使用场景:常用于需要在容器启动或停止时执行特定逻辑的场景,如启动和关闭后台任务。

示例

@Component
public class MySmartLifecycleBean implements SmartLifecycle {
    private boolean running = false;

    @Override
    public void start() {
        System.out.println("Starting MySmartLifecycleBean");
        running = true;
    }

    @Override
    public void stop() {
        System.out.println("Stopping MySmartLifecycleBean");
        running = false;
    }

    @Override
    public boolean isRunning() {
        return running;
    }
}

在 Spring 框架中,确实有许多扩展接口,除了前面提到的,这里再介绍一些更少见但也十分有用的扩展接口。每个接口都有其特定的使用场景,这些接口能帮助开发者在复杂场景下获得更精细的控制:

二十、BeanClassLoaderAware

BeanClassLoaderAware 接口允许 Bean 获取类加载器 ClassLoader。实现该接口的 Bean 可以在运行时动态加载类或资源。

使用场景:当需要在运行时加载类或资源(比如插件加载器、字节码生成)时,该接口会非常有用。

示例

@Component
public class ClassLoaderAwareBean implements BeanClassLoaderAware {
    private ClassLoader classLoader;

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public void loadClass(String className) throws ClassNotFoundException {
        Class<?> clazz = classLoader.loadClass(className);
        System.out.println("Loaded class: " + clazz.getName());
    }
}

二十一、NotificationPublisherAware

NotificationPublisherAware 是 Spring 提供的用于管理 JMX 通知的扩展接口。实现该接口的 Bean 可以通过 NotificationPublisher 来发送 JMX 通知。

使用场景:适用于需要在应用中向外部系统发送 JMX 通知的情况,通常用于系统监控或状态更新。

示例

@Component
public class JmxNotificationBean implements NotificationPublisherAware {
    private NotificationPublisher notificationPublisher;

    @Override
    public void setNotificationPublisher(NotificationPublisher notificationPublisher) {
        this.notificationPublisher = notificationPublisher;
    }

    public void sendNotification(String message) {
        notificationPublisher.sendNotification(new Notification("type", this, 0, message));
    }
}

二十二、LoadTimeWeaverAware

LoadTimeWeaverAware 接口用于获取 LoadTimeWeaver,这是 Spring 用于实现加载时织入(如 AOP)的组件。实现该接口的 Bean 可以在加载时织入特定的逻辑。

使用场景:常用于实现加载时的 AspectJ 织入,以便在运行时动态增强 Bean 的行为。

示例

@Component
public class WeaverAwareBean implements LoadTimeWeaverAware {
    private LoadTimeWeaver loadTimeWeaver;

    @Override
    public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
        this.loadTimeWeaver = loadTimeWeaver;
    }
}

二十三、BeanNameAware

BeanNameAware 接口允许获取当前 Bean 的名称。实现该接口的 Bean 可以在容器初始化时获取它在容器中的名称。

使用场景:适用于需要在运行时知道自身名称的 Bean,常用于调试或在特殊情况下依赖 Bean 名称的逻辑。

示例

@Component
public class BeanNameAwareComponent implements BeanNameAware {
    private String beanName;

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    public void printBeanName() {
        System.out.println("Bean name: " + beanName);
    }
}

二十四、DruidDataSource MBean 扩展

如果项目中使用了阿里巴巴的 Druid 数据源,Spring 也支持将其注册为 MBean 以便进行监控和管理。

使用场景:适合需要监控数据库连接池状态的场景。

示例

@Configuration
public class DruidConfiguration {
    @Bean
    public ServletRegistrationBean<StatViewServlet> druidServlet() {
        ServletRegistrationBean<StatViewServlet> servletRegistrationBean = 
            new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "admin");
        return servletRegistrationBean;
    }
}

二十五、Aspect Oriented Programming (AOP) 相关接口

在 Spring AOP 中,还有一些接口可以用于拦截方法执行,例如 MethodInterceptor。Spring 的 AOP 功能允许通过切面、通知、连接点等机制对方法调用进行增强。

使用场景:适用于需要动态代理或拦截方法调用,加入日志、权限校验、事务管理等横切关注点的场景。

示例

@Aspect
@Component
public class LoggingAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Executing method: " + joinPoint.getSignature().getName());
        Object result = joinPoint.proceed();
        System.out.println("Method executed successfully");
        return result;
    }
}

最后的小总结

1. ApplicationContextAware

  • 描述:用于获取 ApplicationContext 实例。
  • 场景:访问 Spring 容器中的其他 Bean,或获取环境属性。

2. BeanFactoryAware

  • 描述:用于获取 BeanFactory 实例。
  • 场景:动态获取 Bean 或管理 Bean 的生命周期。

3. EnvironmentAware

  • 描述:获取 Environment,访问环境属性和配置文件。
  • 场景:动态读取环境变量或配置文件属性。

4. ResourceLoaderAware

  • 描述:获取 ResourceLoader,加载文件资源。
  • 场景:加载配置文件、图片等资源。

5. MessageSourceAware

  • 描述:获取 MessageSource,访问国际化消息。
  • 场景:多语言支持,动态获取不同语言文本。

6. ApplicationEventPublisherAware

  • 描述:获取 ApplicationEventPublisher,发布自定义事件。
  • 场景:在应用中触发特定事件并通知其他组件。

7. EmbeddedValueResolverAware

  • 描述:获取 StringValueResolver,解析占位符和表达式。
  • 场景:解析属性占位符或表达式。

8. BeanNameAware

  • 描述:获取当前 Bean 的名称。
  • 场景:需要在运行时获取 Bean 名称,调试或依赖名称的逻辑。

9. InitializingBean & DisposableBean

  • 描述InitializingBean 在初始化后调用,DisposableBean 在销毁时调用。
  • 场景:在 Bean 的生命周期中执行初始化或销毁逻辑。

10. SmartInitializingSingleton

  • 描述:容器启动完成后调用实现此接口的所有单例 Bean。
  • 场景:用于容器完全启动后执行特定操作,如数据库检查、缓存加载。

11. FactoryBean

  • 描述:创建复杂 Bean 的工厂类。
  • 场景:Bean 需要复杂构造过程时,使用 FactoryBean 提供实例。

12. ApplicationListener

  • 描述:监听并处理 Spring 容器内的事件。
  • 场景:对容器事件做出反应,如上下文启动、刷新、关闭等。

13. SmartLifecycle

  • 描述:扩展了 Lifecycle 接口,控制启动和停止顺序。
  • 场景:容器启动或停止时执行特定逻辑。

14. LoadTimeWeaverAware

  • 描述:获取 LoadTimeWeaver,支持加载时织入(如 AOP)。
  • 场景:加载时增强 Bean,比如使用 AspectJ 动态代理。

15. AsyncConfigurer

  • 描述:配置自定义异步任务执行器和异常处理器。
  • 场景:自定义异步任务的执行逻辑或处理异步异常。

16. PropertySourcesPlaceholderConfigurer

  • 描述:处理配置文件中的占位符解析,适用于外部配置管理。
  • 场景:从外部属性文件中加载配置,如 .properties 文件。

17. ServletContextAware

  • 描述:获取 ServletContext 实例,适用于 Web 环境。
  • 场景:访问 Web 环境中的资源或管理 Web 容器级别的设置。

18. BeanClassLoaderAware

  • 描述:获取类加载器 ClassLoader
  • 场景:在运行时加载类或资源,如插件加载器。

19. NotificationPublisherAware

  • 描述:管理 JMX 通知,通过 NotificationPublisher 发送通知。
  • 场景:向外部系统发送 JMX 通知,如系统监控。

20. LoadTimeWeaverAware

  • 描述:实现加载时织入,支持动态增强 Bean 行为。
  • 场景:在加载时织入 AOP 增强逻辑,特别是 AspectJ 应用场景。

21. BeanNameAware

  • 描述:获取当前 Bean 的名称。
  • 场景:需要在运行时获取自身名称,适合调试和管理 Bean 名称的情况。

22. DruidDataSource MBean 扩展

  • 描述:在应用使用阿里巴巴 Druid 数据源时,可注册为 MBean 管理。
  • 场景:监控数据库连接池状态,适用于系统监控需求。

23. Aspect Oriented Programming (AOP) 相关接口

  • 描述:如 MethodInterceptor,用于拦截方法调用,实现 AOP。
  • 场景:加入日志、权限校验、事务管理等横切关注点。

这些扩展接口帮助我们实现对 Bean 生命周期、资源管理、事件发布、属性解析等细节的控制。合理使用这些接口可以让应用更加模块化、灵活、符合不同的业务需求。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接