SpringBoot 自动装载 Bean

我们在工作中经常会遇到这样的场景,我们写了很多非常实用的工具类,这些类在多个项目工程中使用非常频繁。如果在每个要使用的项目工程中都去编写加载 bean 的代码的话,那么重复的代码就太多了。如果你想追求完美只写一份代码的话,使用 SpringBoot 的自动装载的特性是一个很不错的方案选择。

本篇博客采用代码的方式介绍如何让 SpringBoot 自动将 bean 装载到 Spring 容器中,然后在要使用的项目中直接使用 @Autowired 注入使用即可,不需要在使用的项目中去写 @Bean 装载代码,以便减少重复的代码编写,在本篇博客的最后会提供 Demo 的源代码下载。


一、搭建工程

本篇博客搭建的工程结构如下所示:

image

common_bean 项目是我们编写的常用工具类,其内部实现 Spring 自动装载 Bean,在实际工作中会比其它很多工程所引用,对于引用 common_bean 的工程来说,它们不需要再编写 @Bean 装载的代码,直接使用 @Autowired 注入使用即可。

use_bean 是引用 common_bean 项目的一个示例项目,在实际工作场景中,应该会有很多。


二、自动装载 Bean 的具体实现

自动装载 Bean 是在 common_bean 这个项目中实现的,本篇博客中只编写了一个工具类 JobsUtils ,实际工作中应该会有很多工具类。JobsUtils 工具类中具体的代码其实并不重要,你可以根据自己的工作需要编写任何有用的方法,我这里编写的代码如下:

package com.jobs.common;

import io.jsonwebtoken.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JobsUtils {

    /**
     * 获取一个字符串的 md5 值
     */
    public String getMd5(String str) {
        if (!StringUtils.isEmpty(str)) {
            return DigestUtils.md5Hex(str);
        }

        return null;
    }

    /**
     * 生成一个 jwt token
     *
     * @param data   要存入 token 中的数据
     * @param secret 数据校验的密钥
     * @param second 设置 token 的有效期(秒)
     * @return
     */
    public String getToken(Map data, String secret, Integer second) {
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, secret)
                .setExpiration(new Date(currentTime + second * 1000))
                .addClaims(data)
                .compact();
    }

    /**
     * 获取 jwt token 中存储的键值对数据
     */
    public Map getClaims(String token, String secret) {
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token).getBody();
        } catch (Exception ex) {
            //无效的 jwt token,要么已经过期,要么被篡改了不合法
            System.out.println(ex.getMessage());
            Map map = new HashMap();
            map.put("info", ex.getMessage());
            return map;
        }
    }

     /**
     * 获取指定位数的随机数字字符串
     *
     * @param len 指定位数长度,例如 6 位数字
     */
    public String getRandomNumber(Integer len) {
        if (len > 0) {
            String result = RandomStringUtils.randomNumeric(len);
            return result;
        }

        return null;
    }
}

我在 JobsUtils 工具类编写的方法很简单,总共 3 个方法:获取md5值,生成token,获取token中的数据。我们编写一个 CommonBeanAutoLoad 类,在这个类中编写将 JobsUtils 实例装载到 Spring 容器中的方法,代码如下:

package com.jobs;


import com.jobs.common.JobsUtils;
import org.springframework.context.annotation.Bean;

public class CommonBeanAutoLoad {

    @Bean
    public JobsUtils getJobUtils() {
        return new JobsUtils();
    }
}

common_bean 只是一个类库,其并不是一个启动程序,它需要被别的项目工程所引用,为了能够在别的项目工程启动后,自动执行 CommonBeanAutoLoad 类的代码将 Bean 加载到 Spring 容器,我们还需要在 common_bean 项目中做一个简单的配置即可。

我们需要在 resources 目录下创建一个 META-INF 目录,然后在其下面创建一个 spring.factories 文件,内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.jobs.CommonBeanAutoLoad

在 spring.factories 文件中,指定自动配置的类名,这里指定 CommonBeanAutoLoad 的完全限定名即可。

在完成了以上步骤后,common_bean 的自动装载代码就编写完成了,很简单吧。


三、验证和使用 Bean 的自动装载

我们使用 use_bean 工程来进行测试,看看 common_bean 中的 JobsUtils 是否自动装载到了 Spring 容器中。

在 use_bean 中编写了一个 TestController 进行测试,里面只有使用 @Autowired 注入 JobsUtils 实例使用。

package com.jobs.controller;

import com.jobs.common.JobsUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RequestMapping("/test")
@RestController
public class TestController {

    //由于 common_bean 项目中自动装载了 JobsUtils
    @Autowired
    private JobsUtils jobsUtils;

    //获取一个字符串的 md5 值
    @GetMapping("/getmd5/{str}")
    public String getLaoYouTiaoEmp(@PathVariable("str") String str) {
        String md5 = jobsUtils.getMd5(str);
        return md5;
    }

    //生成 jwt token
    @GetMapping("/createToken")
    public String getJwtToken(String uname, String depart) {
        Map<String, String> map = new HashMap<>();
        map.put("uname", uname);
        map.put("depart", depart);
        String token = jobsUtils.getToken(map, "jobs666", 30);
        return token;
    }

    //获取 jwt token 中的数据
    @GetMapping("/getTokenData")
    public Map getTokenData(String token) {
        Map res = jobsUtils.getClaims(token, "jobs666");
        return res;
    }

    //获取指定位数的随机数字字符串
    @GetMapping("/getRanIntStr")
    public String getRandomNumber(Integer len) {
        return jobsUtils.getRandomNumber(len);
    }
}

use_bean 由于对外提供测试接口,因此在 application.yml 文件中配置了启动端口为 9527

然后我们就可以请求 TestController 中的方法进行测试了,具体细节可以下载源代码查看,运行测试验证。

目前我们只有一个 use_bean 工程引入 common_bean,实际项目中可以有很多工程引入并自动装载并使用 common_bean 项目,我们只需要在 common_bean 项目中写一份装载 bean 的代码,并在 spring.factories 文件中配置好自动装载的类即可。


本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/springboot_autobean.zip

posted @ 2023-07-23 12:33  乔京飞  阅读(10964)  评论(0编辑  收藏  举报