非 Spring 管理的 Bean 使用 SpringBean

2021-01-27  本文已影响0人  扮鬼之梦

添加Spring工具类

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return applicationContext.getBean(name, clazz);
    }

    //通过Class返回指定的BeanMap
    public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
        return applicationContext.getBeansOfType(clazz);
    }

}

以 RestUtil工具类 使用 RestTemplate(Spring管理的Bean) 为例

1. Spring注入RestTemplate

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class RestConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

2. 创建Rest工具类

import org.springframework.web.client.RestTemplate;

public class RestUtil {

    private static RestTemplate restTemplate;

    static {
    // 使用SpringUtil 设置 RestUtil 的静态属性 restTemplate
        restTemplate = SpringUtil.getBean(RestTemplate.class);
    }

    private RestUtil() {
    }

    public static <T> T get(String url, Class<T> responseType) {
        return restTemplate.getForObject(url, responseType);
    }
}

3. 测试

单元测试代码

@Test
public void restTest(){
    String url = "https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?cardBinCheck=true&cardNo={{银行卡号}}";
    Map map = RestUtil.get(url, Map.class);
    System.out.println(JSON.toJSONString(map));
}

单元测试结果


image

4. 为什么在静态代码块中设置restTemplate?

SpringBoot 启动完成时,RestUtil 没有实例化,RestUtil 的静态方法也未被调用过。所以在调用静态方法或实例化时,一定可以通过 SpringUtil 获取到 Spring Bean。然后 RestUtil 中的 restTemplate 只需要初始化一次,而静态代码块的代码只会执行一次,正好满足需求。

关于类的代码块、静态代码块、构造器的加载时机测试代码

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class RestTest {

    // 实例化测试
    @Test
    void test1() {
        System.out.println("-------------------");
        new A();
        System.out.println("-------------------");
        new A();
        System.out.println("-------------------");
    }

    // 静态方法调用测试
    @Test
    void test2() {
        System.out.println("-------------------");
        A.a();
        System.out.println("-------------------");
        A.a();
        System.out.println("-------------------");
    }

}

class B {
    {
        System.out.println("父类非静态代码块");
    }

    static {
        System.out.println("父类静态代码块");
    }

    public B() {
        System.out.println("父类构造器");
    }
}

class A extends B {
    {
        System.out.println("子类非静态代码块");
    }

    static {
        System.out.println("子类静态代码块");
    }

    public A() {
        System.out.println("子类构造器");
    }

    public static void a() {
        System.out.println("执行方法a");
    }
}

test1结果


test2结果


上一篇下一篇

猜你喜欢

热点阅读