0

我正在开发一个项目,其中预先存在的代码有很多手动设置,并在 main 方法中完成了类的连接——这似乎是 Spring 擅长替换的完美示例。有几个对象共享一个父类 Widget。每个小部件都包含一个它所依赖的其他小部件的列表。

例如,如果您要在代码中编写此代码,它将类似于:

class Widget{ void addDependency(Widget w}{..}}

class A extends Widget{...}
...
class G extends Widget{...}

A a = new A();
...
G g = new G();

a.addDependency(b);
b.addDependency(c);
b.addDependency(d);
b.addDependency(f);
c.addDependency(g);

您显然不能只拥有一个@Autowired 小部件集合,因为那样您将获得所有小部件的集合。@Autowired 有没有办法过滤掉它,所以它只获取某些子类型的实例?

有两种我不喜欢的方法。第一种是连接所有非小部件 bean,并在加载上下文后将 Widget 集合连接在一起。另一种方法是使用 @Resource 连接 ApplicationContext 并使用 @PostConstructor 来获取你想要的需要来自ApplicationContext。两者看起来都不优雅,还有其他方法吗?

4

2 回答 2

1

我可能会像@Matt 那样做,但我可能会考虑创建一个自定义BeanPostProcessor,但我认为 Matt 的方式更安全。

然后我会创建一个自定义注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Dependencies {
    Class<?>[] value();
}

我会将注释放在每个小部件上

@Dependencies({WidgetB.class,WidgetC.class})
public class WidgetA extends Widget {
}

然后你会做@Matt bean 查找(你应该检查Spring 的 BeanFactoryUtils)从bean.getClass().getAnnotation(Dependencies.class).

代替注释,您可以在 bean 上创建一个属性以在其中列出 deps。

于 2012-08-19T15:59:25.670 回答
0

由于您没有包含您在春季使用@PostConstruct 尝试过的示例,这就是我将要做的。

@Component
public WidgetBuilderComponent {
    @Autowired
    private ApplicationContext context;

    @Bean
    public A a() {
        return new A();
    }

    @PostConstruct
    public void populate() {
        A a = a();
        for (B b: context.getBeansOfType(B.class).values()) {
            a.addDependency(b);
        }
    }
}

对于其他类型,您将拥有类似的类。如果您需要给定类型的多个实例,只需创建多个 @Bean 方法,并确保在 @PostConstruct 方法中适当地填充每个方法。请注意,像这样的类不能在同一上下文中多次放置。

你总是可以用 FactoryBean + InitializingBean 替换它,它会完成同样的事情,尽管它会更可重用。

另一种选择是仅使用@Component 进行接线,让您的小部件自行构建而不必担心接线。

@Component
public WidgetPopulatorComponent {
    @Autowired
    private ApplicationContext context;

    @PostConstruct
    public void populate() {
        for (A a: context.getBeansOfType(A.class).values()) {
            for (B b: context.getBeansOfType(B.class).values()) {
                a.addDependency(b);
            }
        }
    }
}
于 2012-08-18T03:25:21.677 回答