V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

请问 Springboot 有没有什么优雅的方法可以调用 getBean(String beanname) 来获取 Bean?

  •  
  •   Newyorkcity · 2019-08-24 11:57:25 +08:00 · 6604 次点击
    这是一个创建于 1678 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的一个 controller 中想要调用一个 Bean,因为整个 controller 只有一个方法用到了它,所以我不希望在 controller 里声明一个成员变量然后注释 @Autowired,而希望在那个方法中用 applicationContext.getBean(...) 这样的方法得到它....

    我知道 ApplicationContextAware 这个接口,但我真心觉得这个接口设计的很奇怪。请见下文的最后。

    下文是我为解决这个问题做了啥,免得有人吐槽我伸手党。


    所以我先以 getbean inurl:docs.spring.io/spring-boot/ 为关键词,试图找到相关的官网资料,无果..

    再以 get applicationcontext inurl:docs.spring.io/spring-boot/ 为关键词搜索,还是没有相关的官网资料

    好吧,那看看 stackoverflow.com 上会不会已经有同样的问题了,以 how to getBean Springboot inurl:stackoverflow.com 为关键词搜索,看起来有个比较靠谱的

    https://stackoverflow.com/questions/34088780/how-to-get-bean-using-application-context-in-spring-boot/38274721

    第一个回答的话,我连在类上添加成员变量再 @Autowired 都不愿意,我还绕个大弯子设个 ApplicationContext 的成员变量,那不更加赘余了么。

    第二个回答说使用 ApplicationContextAware 接口,这个接口的类会在 springboot 启动时被寻找,找到后会自动通知(注入) spring boot 的 ApplicationContext,我觉着应该就是这个了。虽然我觉得工具类还要我自己来写很不可思议(难道开发一个大型项目完全不会出现“一个 Bean 只在一个方法中被使用,为它添加一个成员变量没必要且逻辑混乱”这种情况么?) 然而这个接口的 setApplicationContext 方法居然不是静态方法?!一个工具类不应该都是不实例化的,通过调用静态方法来辅助解决问题的么?这个 setApplicationContext 方法不是静态的,那我 静态的 applicationContext 怎么注入啊。。。

    而且我刚才两次搜索,完全没有搜到 ApplicationContextAware 这个接口的信息。应该以什么关键词去搜索,才能获得这种有用的信息呢?

    谢谢

    6 条回复    2019-10-12 17:02:12 +08:00
    napsterwu
        1
    napsterwu  
       2019-08-24 12:37:02 +08:00
    无解,就是要 Autowire 一个 context 或者 bean。或者可以在初始化之后把 context 注入到一个静态变量里。
    anzu
        2
    anzu  
       2019-08-24 12:57:04 +08:00   ❤️ 1
    后面没看。直接把 Autowire 写在方法参数中啊。
    ```
    public String sayHello(@ Autowired HelloService service) { }
    ```
    这样,HelloService 就会自动绑定了。
    wujichao
        3
    wujichao  
       2019-08-24 13:19:34 +08:00   ❤️ 1
    1. controller 是单例, 他持有的所有对象都是无状态的. 通常情况下减少一个类的成员变量的好处防止状态太多, 难易维护. 既然是无状态的, 注入进来又何妨.
    2. 既然有洁癖, 为啥不一个接口一个 controller 呢
    zhady009
        4
    zhady009  
       2019-08-24 13:39:12 +08:00   ❤️ 1
    @Bean
    public SpringBeanUtil getSpringBeanUtil(ApplicationContext applicationContext) {
    SpringBeanUtil springBeanUtil = new SpringBeanUtil();
    springBeanUtil.setApplicationContext(applicationContext);
    return springBeanUtil;
    }


    public class SpringBeanUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext appContext) throws BeansException {
    applicationContext = appContext;
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
    return (T) applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> requiredType) {
    return applicationContext.getBean(requiredType);
    }
    }
    GM
        5
    GM  
       2019-08-24 15:14:17 +08:00
    ApplicationContextAware 是正解,里别的都是歪门邪道。

    虽然 setApplicationContext 是实例方法,可是 java 并不禁止实例方法给静态属性赋值啊对吧,所以在把 setApplicationContext 注入的 context 存放到一个 static 变量里就可以了,然后就可以在别的静态方法里直接使用了。
    Caelebs
        6
    Caelebs  
       2019-10-12 17:02:12 +08:00
    身为菜鸡 只知道 ApplicationContextAware
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3177 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 12:28 · PVG 20:28 · LAX 05:28 · JFK 08:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.