【SpringBoot】静态方法获取 bean的

背景:

使用 springboot,要从spring容器里面取到一个bean,那是很容易的。
但从静态方法里面取出一个bean,有什么方法呢?

比如:
场景1:要写一个工具类,可以提供静态方法去获取一个bean。
场景2:要写一个工具类,可以提供静态方法去获取一个bean,并且这个工具类不能给spring管理(因为常规操作,交给 spirng管理,就得对包进行扫描,一些公共模块,被多处依赖,被迫添加依赖,总感觉不太好。)
场景3:有一个类,想交给spirng进行管理,但它在公共模块,并不想加注解,也不想加包扫描,如果做这样的修改后,其它用到这个类的地方,会有些影响。该怎样做呢

场景1:要写一个工具类,可以提供静态方法去获取一个bean。

方法比较多,
比如:写一个工具类去实现ApplicationContextAware接口,并把这个工具类交给Spring管理,通过这个工具类中的静态方法从spirng容器里面,通过beanName把 bean 捞出来,

@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext context;

    private ApplicationContextUtil() {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.setContext(applicationContext);
    }

    public static <T> T getBean(Class<T> t) {
        return context.getBean(t);
    }

    public static Object getBean(String name) {
        return context.getBean(name);
    }

    public static void setContext(ApplicationContext context) {
        ApplicationContextUtil.context = context;
    }
}

使用的时候
XXBean xx = ApplicationContextUtil.getBean(XXBean.class);

这种方式,需要把工具类交给Spring管理,然后,使用的地方就不受该限制了,随便哪里可以从spring容器里面找到对应的 bean。

但这个方法就是有个管理,一个工具类,它受到的限制应该越少越好,比如说,不想在工具类上面添加 @Component,并且工具类的路径,也要被扫描,这个工具类才能真正能用起来。

场景2:要写一个工具类,可以提供静态方法去获取一个bean,并且这个工具类不能给spring管理

有没有不交结spirng管理,却可以使用呢?
方法有,自身不想被spring管理,却又想用 spring 容器里面的内容,咋整呢,
来到场景2

想从spirng容器里面拿bean, 重点就在于 spring管理的上下文,就是 context, 如果把 context 拿到后,其实也就好办了。
方法如下:

还是那个工具类,但不需要再加 @Component 这个注解,把它干掉,也不用实现 ApplicationContextAware 了,就一个很普通的工具类,然后它有一个属性 context, 对应spring 里面的 ConfigurableApplicationContext

public class ApplicationContextUtils {

    public static ApplicationContext context;

    public static void setContext(ApplicationContext applicationContext) {
        context = applicationContext;
    }

    public static <T> T getBean(String beanName, Class<T> requiredType) {
        try{
            return context.getBean(beanName, requiredType);
        } catch (Exception e){
            log.error("get bean error, {}", e.getMessage());
            return null;
        }
    }
}

然后在启动方法里面,把 ConfigurableApplicationContext set 进去,比如

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

这样,拿到了 context, 也就可以为所欲为了。
嗯。获取 spirng 容器 bean 的大概如此。。。

场景3:有一个类,想交给spirng进行管理,但它在公共模块,并不想加注解,也不想加包扫描

还有一个问题三,
现在有一个普通的类,想把它加到 spirng 管理, 但又不能对这个类进行任何的修改,就好像是一个第三方的类,想把它加到 Spring 管理。

比如:

import org.springframework.web.client.RestTemplate;

public class DemoApplication {
    // ......

    // 这个 RestTemplate 就是一个普通的类,想把它将给 spring 管理,就可以用这种方法
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

再比如

@Configuration
public class DemoDataAutoConfig {

    @Value("${data.enabled: false}")
    private boolean enabled;

    @Bean
    public DataConfig dataConfig() {
        return new DataConfig(enabled);
    }

}


// DataConfig 就是一个极度普通的类
public class DataConfig {

    private boolean enabled;

    // Getter 和 Setter
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public DataConfig(boolean enabled) {
        this.enabled = enabled;
    }
}

DataConfig 是一个普通类,不能/不想对它做改造,不想去扫描这个包路径,那 @Bean 就是一个很不错的方法了。

以上,做下笔记。

posted @ 2024-09-11 20:30  aaacarrot  阅读(24)  评论(0编辑  收藏  举报