当前位置: 首页 > 知识库问答 >
问题:

如何定义受保护的或私有的beans?

宰父跃
2023-03-14

我有两个配置,代码是这样的。

@RequiredArgsConstructor
public class Foo {
    @Getter
    private final List<Integer> list;
}
@RequiredArgsConstructor
public class Bar {
    @Getter
    private final List<String> list;
}
@Configuration
public class FooConfig {

    @Bean
    public Foo foo() {
        return new Foo(innerList()); //<-- Guess which innerList() it is. It really depends on config loading sequence
    }

    @Bean
    protected List<Integer> innerList() {
        // An ineffective "protected" bean, return type list of int
        ArrayList<Integer> result = new ArrayList<>();
        result.add(1);
        return result;
    }

}
@Configuration
public class BarConfig {

    @Bean
    public Bar bar() {
        return new Bar(innerList()); 
    }

    @Bean
    protected List<String> innerList() {
        // Another "protected" bean, return type list of string
        // but have the same method name with `FooConfig.innnerList()`
        ArrayList<String> result = new ArrayList<>();
        result.add("string");
        return result;
    }
}
@Component
public class Test {

    @Autowired
    @Getter
    private Bar bar;


    @Autowired
    @Getter
    private Foo foo;


    public static void main(String[] args) {
        // Init Spring context 
        // innerList() in the second config always hides the one in the first config, so BarConfig.innerList() is available here
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(FooConfig.class,
                BarConfig.class, Test.class);

// Nothing changes even if disable BeanDefinitionOverriding here
//ctx.setAllowBeanDefinitionOverriding(false);

        Test test = ctx.getBean(Test.class);
        Assert.assertEquals(test.getBar().getList().get(0).getClass(), String.class);
        Assert.assertEquals(test.getFoo().getList().get(0).getClass(), Integer.class);// <-- Foo instance gets a wrong innerList() injected, throwing java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

    }
}

代码未按预期运行。所以我的问题是...

  • 对于bean方法,当bean方法被Spring AOP代理后,使用修饰符<code>public
  • 有没有办法在配置中隐藏bean
  • 在这种情况下,我是否触发了方法注入
  • 由于bean方法在大型项目中可能具有相同的名称,是否有一些最佳实践来避免潜在的冲突(注入意外的bean)

共有1个答案

韩宏朗
2023-03-14

通常,您会期望 Spring 会因“无独一无”定义异常而失败,因为内部列表 bean 有多个定义。

但是您设置它的方式似乎是可行的,可能是因为< code>proxyBeanMethods逻辑中的某些东西使它可行。查看Springs @Configuration中何时将proxyBeanMethods设置为false?

您不能在Spring的配置中隐藏bean。Spring旨在成为一个IoC容器,将应用程序连接在一起,我认为隐藏bean对此不是一个有用的功能

为了避免在大型项目中重叠bean,可以使用不同的类来封装。对于您的示例,您可以将<code>Foo</code>和<code>Bar</code>作为不同的Bean,但<code>innerList

@Configuration
public class BarConfig {

    @Bean
    public Bar bar() {
        return new Bar(innerList()); 
    }

    // private list just for Bar
    private List<String> innerList() {
        ArrayList<String> result = new ArrayList<>();
        result.add("string");
        return result;
    }

}

@Configuration
public class BazConfig {

    // baz really needs foo's list, so we inject Foo as a dependency
    @Bean
    public Baz baz(Foo foo) {
        return new Baz(foo.getList()); 
    }
}
 类似资料:
  • 面向对象编程最重要的原则之一 —— 将内部接口与外部接口分隔开来。 在开发比 “hello world” 应用程序更复杂的东西时,这是“必须”遵守的做法。 为了理解这一点,让我们脱离开发过程,把目光转向现实世界。 通常,我们使用的设备都非常复杂。但是,将内部接口与外部接口分隔开来可以让我们使用它们且没有任何问题。 一个现实生活中的例子 例如,一个咖啡机。从外面看很简单:一个按钮,一个显示器,几个洞

  • 问题内容: 什么时候以及为什么要在类中使用,和函数以及变量?它们之间有什么区别? 例子: 问题答案: 你用: 范围,以使该属性/方法可从任何位置,对象的其他类和实例使用。 当您希望您的属性/方法仅在其自己的类中可见时。 要使属性/方法在扩展当前类的所有类(包括父类)中可见时显示范围。 更多:( 有关全面信息) PHP手册-可见性

  • 问题内容: 关键字授予对相同包和子类(http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html)中的类的访问权限。 现在,每个类都有一个超类(http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html)。 因此,我得出结论,即使每个类都可以访问的方法。

  • 我希望使用基于UML模型的genmodel生成Java代码。 我正在使用Papyrus的Eclipse Oxygen,UML模型(使用了一些Ecore配置文件),以便使用GenModel向导生成Ecore,最终生成模型Java代码(标准Eclipse插件)。 我已将生成的源代码与手写的源代码分开,因此将避免+手动修改解决方案:) null

  • 是否可以实现一个接口,然后在重写方法时,使方法私有或受保护?

  • 问题内容: 我正在阅读一些Java文本,文本说我们只能为类和接口应用或访问修饰符。因此,如果我们声明以下内容,则会产生编译错误: 要么 我很好奇为什么类或接口不能接收或访问修饰符? 问题答案: 表示“仅在封闭类中可见”。 表示“仅在封闭类和任何子类中以及封闭类包中的任何位置可见”。 因此,应用于顶级类没有任何意义;的定义的第一部分也是如此。的第二部分 可能 适用,但是它被默认的(受包装保护)修饰符