spring是否能在其它bean完成init之后才创建另外一个bean的实例?

pngx
  • 87

有个需要引用bean的工具类

@Component
class FooUtils implements InitializingBean {
    private static Foo foo;
    private static Bar bar;

    @Autowired
    private void foo(Foo foo) {
        MyFactory.foo = foo;
    }    

    @Override
    public void afterPropertiesSet() throws Exception {
        bar = new Bar(foo, ...);
    }
    
    public static MyObj create(int param1, int param2, int param3) {
        if (foo == null) { thrown new Exception(); }
        return new MyObj(foo.baz(param1, param2), bar, param3);
    }
}

想用上面那个工具类创建bean

@Configuration
@DependsOn('fooUtils') // <-- 然而不work, 开始new实例的时候都还没进行bean的init
class Config {
    @Bean
    public MyObj myObjBean() {
        return FooUtils.create(1, 2, 3); // <-- 想不到怎么让这里在fooUtils完成autowired之后才执行
    }
}
@Service
class MyService {
    @Autowired
    private MyObj myObj;
}
回复
阅读 1.2k
3 个回答

请看spring有关DependsOn注解的注释,我这里列出来。


/**
 * Beans on which the current bean depends. Any beans specified are guaranteed to be
 * created by the container before this bean. Used infrequently in cases where a bean
 * does not explicitly depend on another through properties or constructor arguments,
 * but rather depends on the side effects of another bean's initialization.
 *
 * <p>May be used on any class directly or indirectly annotated with
 * {@link org.springframework.stereotype.Component} or on methods annotated
 * with {@link Bean}.
 *
 * <p>Using {@link DependsOn} at the class level has no effect unless component-scanning
 * is being used. If a {@link DependsOn}-annotated class is declared via XML,
 * {@link DependsOn} annotation metadata is ignored, and
 * {@code <bean depends-on="..."/>} is respected instead.
 *
 * @author Juergen Hoeller
 * @since 3.0
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {

    String[] value() default {};

}

注意到其中一句话了吗?

Using {@link DependsOn} at the class level has no effect unless component-scanning
s being used.

如果用在类上面,类上面需要加@ComponentScan("xxxxx")注解。

改成,还不行就把create改成实例方法

    @Bean
    public MyObj myObjBean(FooUtils utils) {
        return FooUtils.create(1, 2, 3);
    }

你这样子写相当于建了一个Bean:fooUtils,但是你调用的是FooUtils,这两个不是同一个实例。

如何解决。

  1. 将调用改成fooUtils
  2. 在FooUtils的create方法里面使用getBean拿到想要使用的Bean
  3. 改变实现工具类的思路,避免在工具类中引用Bean
你知道吗?

宣传栏