首页 > 其他分享 >Spring框架中的依赖检查机制详解

Spring框架中的依赖检查机制详解

时间:2024-09-02 11:22:26浏览次数:11  
标签:context 框架 Spring springframework 详解 ServiceBean org serviceBean public

在大型项目开发中,多个开发者并行工作时,确保所有必需的依赖项都已正确设置是至关重要的。理想情况下,这种检查应该在编译时进行,如果不可能,那么至少在应用启动时尽早进行,以避免在缺少值时出现NullPointerException。Spring框架提供了多种在启动时进行依赖检查的机制。本文将探讨Spring框架在依赖检查方面的一些方面和选项。

构造器注入与Setter注入

在我们之前的教程中,我们讨论了依赖注入的不同方式,我们总是应该使用基于构造器的注入来处理必需的属性(并进行程序化的参数验证),而使用基于Setter的注入来处理可选属性。尽管如此,我们可能仍有许多理由选择使用Setter而不是构造器来注入必需的属性。可能是因为我们的构造器变得过于复杂,也可能是我们稍后想要重新配置某些属性(当然,在这种情况下它们不能是final的,但在连接时仍然是必需的)。

通过构造器进行依赖注入

如果缺少目标构造器所需的依赖项,Spring会抛出UnsatisfiedDependencyException

package com.logicbig.example;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@ComponentScan(useDefaultFilters = false,
        includeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "ConstructorDiExample"))
public class ConstructorDiExample {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(ConstructorDiExample.class);
        ClientBean bean = context.getBean(ClientBean.class);
        bean.doSomething();
    }
    @Component
    private static class ClientBean {
        private final ServiceBean serviceBean;
        private ClientBean(ServiceBean serviceBean) {
            this.serviceBean = serviceBean;
        }
        void doSomething() {
            System.out.println("doing something with: " + serviceBean);
        }
    }
    //uncomment @service to get rid of UnsatisfiedDependencyException       
    //         private class ServiceBean {
    //         }
}
输出
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.logicbig.example.ConstructorDiExample$ServiceBean' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}  

在Setter注入中检查必需属性

如果我们是通过Setter进行必需依赖的注入,那么有以下几种依赖检查的选项:

使用Setter注入

对于Setter注入,我们不需要使用@Autowired。但对于依赖检查,我们需要明确使用这个注解。@Autowired注解的required属性默认为true。因此,如果Setter没有提供依赖项,Spring会抛出UnsatisfiedDependencyException

package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Configuration
@ComponentScan(useDefaultFilters = false,            includeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "SetterAutowiredExample"))
public class SetterAutowiredExample {
    public static void main(String... strings) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                SetterAutowiredExample.class);
        ClientBean bean = context.getBean(ClientBean.class);
        bean.doSomething();
    }
    @Component
    public static class ClientBean {            private ServiceBean serviceBean;
        public void setServiceBean(ServiceBean serviceBean) {
            this.serviceBean = serviceBean;
        }
        public void doSomething() {
            System.out.println("doing something with : " + serviceBean);
        }
    }
    //uncomment following to  get rid of UnsatisfiedDependencyException
    //@Service
    public static class ServiceBean {
    }
}
输出
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.logicbig.example.SetterAutowiredExample$ClientBean': Unsatisfied dependency expressed through method 'setServiceBean' parameter 0: No qualifying bean of type 'com.logicbig.example.SetterAutowiredExample$ServiceBean' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}  

PostConstruct方法中手动执行验证

PostConstruct方法中手动执行验证:

package com.logicbig.example;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import jakarta.annotation.PostConstruct;

public class PostConstructExample {
    public ClientBean clientBean (ServiceBean serviceBean) {
        ClientBean clientBean = new ClientBean();
        //uncomment following to get rid of IllegalArgumentException
        //clientBean.setServiceBean(serviceBean);
        return clientBean;
    }
    public ServiceBean serviceBean () {
        return new ServiceBean();
    }
    public static void main (String... strings) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(
                        PostConstructExample.class);
        ClientBean bean = context.getBean(ClientBean.class);
        bean.doSomething();
    }
    public static class ClientBean {
        private ServiceBean serviceBean;
        public void myPostConstructMethod () throws Exception {
            // we can do more validation than just checking null values here
            if (serviceBean == null) {
                throw new IllegalArgumentException("ServiceBean not set");
            }
        }
        public void setServiceBean (ServiceBean serviceBean) {
            this.serviceBean = serviceBean;
        }
        public void doSomething () {
            System.out.println("doing something with: " + serviceBean);
        }
    }
    public static class ServiceBean {
    }
}
输出
Caused by: java.lang.IllegalArgumentException: ServiceBean not set  

使用InitializingBean接口

InitializingBean定义

(版本:spring-framework 6.1.2)

package org.springframework.beans.factory;
........
public interface InitializingBean {
    void afterPropertiesSet() throws Exception; 1
}
| 1| Invoked by the Spring container after it has set all bean properties.
This method allows the bean instance to perform validation of its overall
configuration and final initialization when all bean properties have been set.  
示例
package com.logicbig.example;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

public class InitializingBeanExample {
    public ClientBean clientBean() {
        return new ClientBean();
    }
    //remove following comment to fix java.lang.IllegalArgumentException: ServiceBean not set
    //        public ServiceBean serviceBean() {
        return new ServiceBean();
    }
    public static void main(String... strings) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(
                        InitializingBeanExample.class);
        ClientBean bean = context.getBean(ClientBean.class);
        bean.doSomething();
    }
    private static class ClientBean implements InitializingBean {
        private ServiceBean serviceBean;
        public void setServiceBean(ServiceBean serviceBean) {
            this.serviceBean = serviceBean;
        }
        public void doSomething() {
            System.out.println("doing something with: " + serviceBean);
        }
        public void afterPropertiesSet() throws Exception {
            if (serviceBean == null) {
                throw new IllegalArgumentException("ServiceBean not set");
            }
        }
    }
    private static class ServiceBean {
    }
}
输出
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientBean' defined in com.logicbig.example.InitializingBeanExample: ServiceBean not set  
    Caused by: java.lang.IllegalArgumentException: ServiceBean not set  

示例项目

使用的依赖和技术:

  • spring-context 6.1.2 (Spring Context)
    版本兼容性:4.3.0.RELEASE - 6.1.2版本列表
    ×
    spring-context的版本兼容性与此示例:
    • 4.3.0.RELEASE
    • 4.3.1.RELEASE
    • …(省略中间版本)
    • 6.1.2
      绿色版本已测试。
  • jakarta.jakartaee-api 10.0.0 (Eclipse Foundation)
  • JDK 17
  • Maven 3.8.1

兼容的Java版本:17+

此博客文章详细介绍了如何在Spring框架中进行依赖检查,包括构造器注入、Setter注入以及通过PostConstruct方法和InitializingBean接口进行手动验证。通过这些机制,可以确保在应用启动时或编译时就发现并处理依赖问题,从而避免运行时错误。

标签:context,框架,Spring,springframework,详解,ServiceBean,org,serviceBean,public
From: https://blog.csdn.net/m0_62153576/article/details/141815512

相关文章

  • .NET 8.0 前后分离快速开发框架
    前言大家好,推荐一个.NET8.0为核心,结合前端Vue框架,实现了前后端完全分离的设计理念。它不仅提供了强大的基础功能支持,如权限管理、代码生成器等,还通过采用主流技术和最佳实践,显著降低了开发难度,加快了项目交付速度。如果你需要一个高效的开发解决方案,本框架能帮助大家轻松应......
  • 求从一固定点到其余点的最短路算法及其matlab程序详解
    #################本文为学习《图论算法及其MATLAB实现》的学习笔记#################算法用途从一固定点到其他所有点的最短路的求法算法思想利用求任意两点间最短路的程序,即可求出从固定点到其他所有点的最短路,从而得到所有的最短路和最短距离。若想查看每条通路所包......
  • Springboot实战——黑马点评之互斥锁
    Springboot黑马点评(3)——优惠券秒杀【还剩Redisson的最后两节没测试后续补上】另外,后期单独整理一份关于分布式锁笔记1优惠券秒杀实现1.1用户-优惠券订单设计1.1.1全局ID生成器使用数据库自增ID作为订单ID存在问题1.1.2考虑全局唯一ID生成逻辑时间戳(Long类型......
  • 基于SpringBoot的房屋交易平台设计与实现
     作者主页:编程指南针作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期......
  • 基于SpringBoot的房屋交易平台设计与实现
     作者主页:编程指南针作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待......
  • MySQL Replication 主从复制详解
    1.1主从复制基础概念在了解主从复制之前必须要了解的就是数据库的二进制日志(binlog),主从复制架构大多基于二进制日志进行,二进制日志相关信息参考:http://www.cnblogs.com/clsn/p/8087678.html#_label61.1.1二进制日志管理说明二进制日志在哪?如何设置位置和命名?......
  • 【2025】基于springboot的高校学生食堂点餐系统(源码+文档+调试+答疑)
    ......
  • PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
    大家好,我是码农先森。我们在某宝或某多多上抢购商品时,如果只是下了订单但没有进行实际的支付,那在订单页面会有一个支付倒计时,要是过了这个时间点那么订单便会自动取消。在这样的业务场景中,一般情况下就会使用到延时队列。通常在客户下单之后,就会将订单数据推送到延时队列中并且......
  • 土壤湿度传感器详解(STM32)
    目录一、介绍二、传感器原理1.原理图2.引脚描述三、程序设计main.c文件TS.h文件TS.c文件四、实验效果 五、资料获取项目分享一、介绍        传感器适用于土壤的湿度检测,模块中蓝色的电位器是用于土壤湿度的阈值调节,数字量输出DO可以与单片机直接相连,通......
  • 枚举与stream流详解
    1枚举语法特点枚举是jdk1.5提供的一个特性枚举是一个特殊的类,这个类的对象的数量是有限的。在定义枚举类的同时就已经确定了类对象及类对象的数量。枚举使用enum关键字定义在枚举类中的第一行,就需要提供枚举类的对象(名字)多个对象名之间使用逗号隔开。最后一个对象可......