SpringBoot自动装配原理学习与实战运用

这篇具有很好参考价值的文章主要介绍了SpringBoot自动装配原理学习与实战运用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、本文概览

我们知道SpringBoot就是框架的框架,它解决了Spring在开发过程中繁琐的配置问题。例如在引入web、aop、data、cache等等场景,以往我们使用Spring时,会需要向容器中手动配置DispatchServlet、 AspectJAutoProxyingConfiguration等等配置类,而使用SpringBoot框架后,只需要引入spring-boot-starter-xxx的jar包,即可自动完成相关场景的配置。
这项技术SpringBoot是如何帮助我们实现的呢?本篇文章就来详细聊聊其中的技术细节。

二、了解自动装配

1、什么是自动装配

首先我们通过一小段代码来了解一下使用SpringBoot完成自动装配的过程。

@SpringBootApplication
public class SpringbootAutoconfigureApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootAutoconfigureApplication.class, args);
    }

}
 <dependencies>
<!--    web自动装配 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
<!--    自动重启 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
<!--    yml配置提示 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
<!--    lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
<!--    单元测试 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

我们创建一个SpringBoot项目,然后引入spring-boot-starter-web jar包,有关于web相关的配置类SpringBoot就会自动帮助我们配置好,我们通过启动类的代码来验证一下:

@SpringBootApplication
public class SpringbootAutoconfigureApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootAutoconfigureApplication.class, args);

        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }
}

...
// 请求处理的bean
dispatcherServlet
// 视图解析器
viewResolver
// 文件上传
multipartResolver
// 字符编码 防止乱码
characterEncodingFilter
...
// 还有很多配置的类,这里就略过了

通过上面一小段的demo,我们可以认知到自动装配就是无需我们在手动配置Bean到Spring容器中,这部分工作由框架给实现了。

2、SpringBoot提供的自动装配

如果要了解SpringBoot为我们提供了哪些自动装配,我们可以通过两种途径去了解:

  • 查看spring-boot-autoconfigure jar包下的模块
  • 通过官网了解:https://docs.spring.io/spring-boot/docs/2.7.10/reference/html/using.html#using.build-systems.starters

image.pngimage.png
了解有哪些自动装配后,也需要了解需要配置的相关信息,例如配置DataSource数据源时,虽然框架替我们配置Bean,但是Bean的一些必要信息也是需要我们提供的,配置哪些信息以及如何配置我们也有两种方式来了解:

  • 通过spring-boot-starter-autoconfigure的xxAutoConfig了解
  • 通过官网了解 https://docs.spring.io/spring-boot/docs/2.7.10/reference/html/application-properties.html#appendix.application-properties

3、定制化配置

SpringBoot提供的自动装配已经满足我们绝大部分业务场景,如果还需要一些自定义内容,我们可以自己定义自动装配jar包,然后在项目中引用,至于怎么操作,我们通过下面章节的学习后即可学会如何定义开发。

三、底层注解以及API

1、底层注解

在了解自动装配的原理前,我们需要了解学习一些底层的注解。
Spring注解.png

2、添加组件

往Spring容器中添加组件的注解。

  • @Bean 标注在方法上
  • @Configuration 标注在类上,表明该类是一个配置类
  • @Component 标注在类上,表明该类是一个普通组件
  • @Controller 标注在类上,表明该类是控制层的Bean
  • @Server 标注在类上,表明该类是服务层的Bean
  • @Repository 标注在类上,表明该类是DAO层的Bean

每个注解的共同作用都是向容器中注册Bean,但又区分不同意义的Bean,所以这些注解也有一个特殊的名字-模式注解。

3、配置绑定

与yml、properties文件的一些配置绑定的Bean

我们可以通过@ConfigurationProperties 与 @Component 组合达到配置绑定的目的;也可以通过@EnableConfigurationProperties与@ConfigurationProperties/进行配置绑定。
下面我们来看下demo:

  • 通过@ConfigurationProperties 与 @Component
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String username;
    private String password;
}
  • @EnableConfigurationProperties
@Configuration
@EnableConfigurationProperties(UserProperties.class)
public class AppConfiguration {
}
@ConfigurationProperties(prefix = "user")
@Data
@ToString
public class UserProperties {
    private String username;
    private String password;
}

测试一下:
image.png

4、按需加载

我们通过spring-boot-autoconfigure jar包可以看到springboot帮助我们设置了了非常多的自动装配类,但是这些配置中并不是我们所有的都需要,只有在需要时才会被注册进Spring容器中。对于这部分的实现,SpringBoot是使用条件注解进行按需加载。例如AOP的自动配置类:

@AutoConfiguration
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
		static class JdkDynamicAutoProxyConfiguration {

		}

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		static class CglibAutoProxyConfiguration {

		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
			matchIfMissing = true)
	static class ClassProxyingConfiguration {

		@Bean
		static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
			return (beanFactory) -> {
				if (beanFactory instanceof BeanDefinitionRegistry) {
					BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
				}
			};
		}

	}

}

下面介绍下出现在本配置类的注解以及没在本类出现其他常用条件注解:

注解 注解意义
@AutoConfiguration 它是一个组合注解,表明这是一个自动配置类,需要注册进IoC容器中,并在此基础上还可以指定在某个配置类注册前或者后进行注册。
@Configuration 表明该类是一个配置类,它有一个参数proxyBeanMethods比较重要:当它为true时,它内部所有的bean注册方法在被任何地方调用的时候都是单例的;当它为false时,它内部的bean注册方法没被调用一次,都会产生一个新的对象。当明确该配置类的配置无依赖关系的时候,可以采用false,减少判断,加速容器的启动。
@ConditionalOnProperty 条件注解,判断当spring的属性配置中有prefix配置,以及该配置中有name指定的配置,并且值为havingValue时,条件通过,当然也可以指定默认配置matchIfMissing
@ConditionalOnExpression 条件注解,符合SpEL表达式时条件通过
@ConditionalOnJava 条件注解,比指定Java版本 高、相等、低 通过条件判断,高、相等、低也是通过配置
@ConditionalOnClass 条件注解,当类路径中存在某个类文件时,条件通过
@ConditionalOnMissingClass 条件注解,当类路径中不存在某个类文件时,条件通过
@Profile 条件注解的一种,指定应用所处的环境可以注册当前Bean,例如dev、test、staging、prod
@ConditionalOnWebApplication 条件注解,指定Web应用为某一类型时进行注册,类型包括ANY、SERVLET、REACTIVE
@ConditionalOnResource 条件注解,指定类路径下有某一资源文件时,条件判断通过
@ConditionalOnMissingBean 条件注解,指定容器中不包含有某一Bean实例时才会通过
@ConditionalOnBean 条件注解,指定容器中包含某一Bean实例时才会通过

上述的注解对于我们了解自动装配的原理足够了。也正是通过上述的配置,SpringBoot实现了按需加载配置Bean的功能。

四、自定义装配组件

通过上面章节的叙述,我们大概知道自动装配的原理是通过spring-boot-autoconfigure进行的注册(框架帮助我我们配置)以及按需加载的原理是通过条件注解实现的。
下面我们也手动定义一个jar包,开发一些功能,然后接入SpringBoot,框架帮我们自动注册。

假设有这样一个需求,在web开发中,对某些接口进行白名单准入,我们可以通过自定义组件注册到容器当中对目标方法进行拦截,注册的动作通过SpringBoot进行自动装配而无需我们配置。

第一步:新建一个工程,用来编写自定义组件。

目录结构如下图所示:
image.png

  • WhiteList代码
package com.markus.middleware.whitelist.annotation;

import java.lang.annotation.*;

/**
 * @author: markus
 * @date: 2023/4/9 2:59 PM
 * @Description: 白名单注解
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WhiteList {
    /**
     * 白名单命中时,是否通过此方法,如果不准入,则返回responseJson 否则正常执行目标方法
     *
     * @return
     */
    boolean passAfterHit() default true;

    /**
     * 不执行目标方法时返回的内容
     *
     * @return
     */
    String responseJson() default "";
}
  • WhiteListJudgeAspect
package com.markus.middleware.whitelist.aspect;

import com.markus.middleware.whitelist.annotation.WhiteList;
import com.markus.middleware.whitelist.config.WhiteListProperties;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author: markus
 * @date: 2023/4/9 3:03 PM
 * @Description:
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */
@Aspect
@Component
public class WhiteListJudgeAspect {

    @Resource
    private List<String> whitelist;

    @Pointcut("@annotation(com.markus.middleware.whitelist.annotation.WhiteList)")
    public void pointcut() {

    }

    // 逻辑写的非常简单,实际并不是这样
    @Around(value = "pointcut()")
    public Object proceed(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = pjp.getTarget().getClass().getMethod(signature.getName(), signature.getParameterTypes());

        WhiteList whiteList = method.getAnnotation(WhiteList.class);
        if (whiteList == null) {
            return pjp.proceed();
        }

        Object[] args = pjp.getArgs();
        if (args.length == 0) {
            return pjp.proceed();
        }

        // 我们假定选择第一个参数就是用户名
        if (whitelist.contains(args[0])) {
            // 放行
            return pjp.proceed();
        } else {
            return whiteList.responseJson();
        }
    }
}

第二步:配置绑定

也就是接入方需要在自己的项目中需要配置的内容:

package com.markus.middleware.whitelist.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.List;

/**
 * @author: markus
 * @date: 2023/4/9 3:08 PM
 * @Description: 白名单配置绑定
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */
@ConfigurationProperties(prefix = "whitelist")
@Data
public class WhiteListProperties {
    private List<String> users;
}

第三步:实现自动装配

  • 配置类实现-WhiteListAutoConfig
package com.markus.middleware.whitelist.config;

import com.markus.middleware.whitelist.aspect.WhiteListJudgeAspect;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * @author: markus
 * @date: 2023/4/9 3:04 PM
 * @Description: 白名单自动配置
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */
@Configuration
@EnableConfigurationProperties(WhiteListProperties.class)
@ConditionalOnClass(WhiteListProperties.class)
public class WhiteListAutoConfig {

    @Bean("whitelist")
    @ConditionalOnMissingBean
    public List<String> whitelist(WhiteListProperties whiteListProperties) {
        return whiteListProperties.getUsers();
    }
}
  • 在类路径下配置META-INF/spring.factories,这样SpringBoot框架就能扫描到我们自定义的配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.markus.middleware.whitelist.config.WhiteListAutoConfig

第四步:业务方接入

  • 引入jar包文件
<dependency>
    <groupId>com.markus</groupId>
    <artifactId>middleware-whitelist</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
  • 配置白名单信息
whitelist:
  users:
    - markuszhang
    - luna
  • 在业务类上加入@WhiteList注解
package com.example.springboot.autoconfigure.controller;

import com.example.springboot.autoconfigure.properties.Person;
import com.example.springboot.autoconfigure.properties.UserProperties;
import com.markus.middleware.whitelist.annotation.WhiteList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author: markus
 * @date: 2023/4/8 10:26 PM
 * @Description:
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */
@RestController
public class HelloController {

    @RequestMapping("/properties")
    public String properties() {
        return "use @EnableConfigurationProperties " + userProperties + " and use @Component " + person;
    }

    @WhiteList(responseJson = "{\n" +
            "    \"code\":\"500\",\n" +
            "    \"msg\":\"非白名单可访问用户拦截\",\n" +
            "    \"data\":\"null\"\n" +
            "}")
    @RequestMapping("/whitelist/test")
    public String whitelist(@RequestParam String userId) {
        return "Hello SpringBoot User " + userId;
    }

}

第五步:测试验证

属于白名单配置的用户:
image.png
image.png
不属于白名单配置的用户:
image.png

五、本文总结

通过本文的叙述,我们掌握了如下内容:文章来源地址https://www.toymoban.com/news/detail-411928.html

  • 什么是自动装配
  • SpringBoot已经提供的自动装配类
  • 底层的注解和API内容学习
  • 以及掌握上述内容后,如何自定义开发一套接入SpringBoot的组件实现自动装配

到了这里,关于SpringBoot自动装配原理学习与实战运用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Springboot中SpringSecurity自动装配原理,源码级别绝对详细

    (1)Springboot有一个自动配置类 SecurityFilterAutoConfiguration , SecurityFilterAutoConfiguration 只要当项目中引入了SpringSecurity的相关jar包就会被自动加载。装载这个类是干嘛的呢? (2)如下图, SecurityFilterAutoConfiguration 自动配置类主要用于,当存在名字叫做\\\"springSecurityFilterChain\\\"的bea

    2024年02月05日
    浏览(36)
  • SpringBoot源码解读与原理分析(六)WebMvc场景的自动装配

    了解了SpringBoot的自动装配机制之后,研究一个常见且实用的场景:当项目整合SpringWebMvc后SpringBoot的自动装配都做了什么? 2.6.1 WebMvcAutoConfiguration 引入spring-boot-starter-web依赖后,SpringBoot会进行WebMvc的自动装配,处理的核心是一个叫WebMvcAutoConfiguration的自动配置类。 由以上源码

    2024年02月21日
    浏览(34)
  • spring自动装配原理

    为了搞明白自动装配原理,需要知道spring容器管理bean的生命周期 分为四步: 1、实例化 读取spring配置文件 通过反射进行bean的实例化(eg:通过BeanFactory实例化) 2、属性赋值 解析 自动装配 (byName、byType、constractor、default)DI的体现 循环依赖 3、初始化 调用XXXAware回调方法

    2024年02月02日
    浏览(25)
  • Spring Boot 自动装配原理

    Java面试题目录 Spring Boot自动装配原理   Spring Boot启动类上的 @SpringBootApplication 注解中包含 @EnableAutoConfiguration 注解,表示开启自动装配。在@EnableAutoConfiguration注解中使用@Import注解引入 AutoConfigurationImportSelector 组件,此类中通过 SpringFactoriesLoader.loadFactoryNames() 方法来扫描所有

    2024年01月25日
    浏览(30)
  • SpringBoot源码-自动装配

      springboot的核心注解@SpringBootApplication 接着看 @SpringBootApplication 注解 截图: 代码:  接着看红框的注解 @EnableAutoConfiguration 截图: 代码:  接着看红框的 AutoConfigurationImportSelector.class 这个类 截图: 接着看接口 DeferredImportSelector 的实现 截图: 在这个DeferredImportSelector类中,

    2024年02月08日
    浏览(25)
  • Springboot的自动装配解读

    目录   1.Springboot的自动装配 1.1 组件装配 1.1.1 组件 1.2 Spring Framework 的模块装配 1.2.1 @Import注解 1.2.2 BeanDefinition  1.3 Spring Framework 的条件装配 1.3.1 @Profile 1.3.2 @Conditional  1.3.3 MetaData元数据接口(补充) AnnotatedTypeMetadata AnnotationMetadata MethodMetadata  1.4 SPI机制 1.5 Springboot 的装配机

    2024年02月11日
    浏览(27)
  • springBoot自动装配机制

    自动配置原理 @SpringBootApplication 是一个组合注解,由 @ComponentScan、@EnableAutoConfiguration 和 @SpringBootConfiguration 组成 @SpringBootConfiguration 与普通 @Configuration 相比,唯一区别是前者要求整个 app 中只出现一次 @ComponentScan excludeFilters - 用来在组件扫描时进行排除,也会排除自动配置类

    2024年02月08日
    浏览(34)
  • springBoot 自动装配

    1.前言 自动装配则是 SpringBoot 的核心,自动装配是如何实现的呢?为什么我们只要引入一个 starter 组件依赖就能实现自动装配呢,接下来就让我们一起来探讨下 SpringBoot 的自动装配机制 2.自动装配原理 提到自动装配,那么你首先得知道JDK的SPI(serviceproviderinterface)机制,因为

    2024年02月09日
    浏览(27)
  • Spring Boot自动装配原理(易懂)

    熟练使用Spring Boot那么自动装配原理的掌握是必不可少的 Spring Boot的自动装配实际上是从 META-INF/spring.factories 文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给Spring容器进行管理 启动类的@SpringBootAppliation注解是一个组合注解,由以下3个注解组

    2024年02月16日
    浏览(31)
  • spring boot的自动装配原理

    作者: 逍遥Sean 简介:一个主修Java的Web网站游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言! Spring Boot是一个开源的Java框架,可以帮助开发者快速构建基于Spring的应用程序。Spring Boo

    2024年02月10日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包