【问题标题】:Spring/LDAP - Invoking setter methods in beans configurationSpring/LDAP - 在 bean 配置中调用 setter 方法
【发布时间】:2011-01-24 18:27:14
【问题描述】:

我正在编写一个 Spring LDAP 应用程序,我必须为我的 ContextSource 设置身份验证策略。我想在我的 beans XML 文件中执行此操作。 JavaDoc for ContextSource 表示它有一个名为

的 setter 方法
setAuthenticationStrategy(
    DirContextAuthenticationStrategy authenticationStrategy
)

要从我的 beans 文件中调用这个 setter,以下 XML 是否足够?

<bean id="authStrategy"
    class="org.springframework...DefaultTlsDirContextAuthenticationStrategy">
 ...
</bean>

<bean id="contextSource"
    class="org.springframework.ldap.core.support.LdapContextSource">

    <property name="url" ... />
    <property name="base" ... />
     ...
    <property name="authenticationStrategy" ref="authStrategy" /> 
</bean>

也就是说,究竟是什么决定了方法setAuthenticationStrategy的调用呢?是不是我的财产名称是authenticationStrategy? Spring 是否会自动将属性名称转换为适当的 setter 方法?

【问题讨论】:

    标签: java spring javabeans spring-ldap


    【解决方案1】:

    实际上,您误解了 JavaBean 上下文中“属性”一词的含义。

    Bean 属性与字段

    JavaBeans 标准(Spring 紧随其后)将 Bean 属性定义为具有遵循特定命名约定的 Getter 方法和/或 Setter 方法的东西:

    对于属性“Bar foo”,getter Bar getFoo()(或 isFoo() 用于布尔属性)或 setter setFoo(Bar) 必须存在(或两者都存在),但不必存在名为“富”。按照惯例,通常会有一个与属性同名的字段,但这绝不是必需的。

    例如以下类(符合 JavaBeans 标准)有一个整数类型的 bean 属性“foo”,尽管底层字段称为 iAmNotFoo 并且是字符串类型。

    public class Dummy {
        private String  iAmNotFoo;
        public Integer getFoo() {
            return  Integer.valueOf(this.iAmNotFoo);
        }
    
        public void setFoo(final Integer foo) {
            this.iAmNotFoo = foo.toString();
        }
    }
    

    我们可以用下面的代码来检验这个假设:

    public static void main(final String[] args) throws Exception {
        for (final PropertyDescriptor descriptor :
            Introspector
                .getBeanInfo(Dummy.class, Object.class)
                .getPropertyDescriptors()) {
            System.out.println(
                "Property: "
                + descriptor.getName()
                + ", type: "
                + descriptor.getPropertyType()
            );
        }
        for (final Field field : Dummy.class.getDeclaredFields()) {
            System.out.println(
                "Field: " 
                + field.getName() 
                + ", type: " 
                + field.getType());
        }
    }
    

    输出:

    属性:foo,类型:类 java.lang.Integer
    字段:iAmNotFoo,类型:class java.lang.String

    Spring 中的属性

    正如我上面所说,Spring 使用这种精确的机制来设置属性。所以当你像这样配置一个bean时

    <bean class="Dummy">
        <property name="foo" value="123" />
    </bean>
    

    “foo”指的是 bean 属性“foo”,因此指的是 setter setFoo()

    这使得如下构造成为可能:

    public class Dummy2 {
        private List<String> foos;
        public void setFoos(List<String> foos) {
            this.foos = foos;
        }
        public void setFoo(String foo){
            this.foos = Collections.singletonList(foo);
        }
    }
    

    您可以按如下方式接线

    <bean class="Dummy2">
        <!-- either set a single value -->
        <property name="foo" value="123" /> 
        <!-- or a list of values -->
        <property name="foos"> 
            <util:list>
                <value>Abc</value>
                <value>Xyz</value>
                <value>123</value>
                <value>789</value>
            </util:list>
        </property>
    </bean>
    

    如您所见,setter 方法与 Spring 相关,而不是实际的字段。

    因此,在 JavaBeans 中:Field != Property,尽管在大多数情况下存在与属性相同类型和名称的字段。

    【讨论】:

    • 感谢您的精彩回答!
    【解决方案2】:

    您的怀疑是正确的:Spring 将属性名称转换为 setter 方法。

    您用作参数的 bean 是 DefaultTlsDirContextAuthenticationStrategy 类型,并且该方法接受 DirContextAuthenticationStrategy 类型的对象,因此 DefaultTlsDirContextAuthenticationStrategy 必须是 DirContextAuthenticationStrategy 的实现者的子类。

    【讨论】:

    • @ktm5124:这个答案是完全错误的。 Spring 不需要翻译任何东西。属性名称仅从设置器名称派生,字段与它无关。在 99% 的情况下,输出是相同的,因为通常有一个底层字段,但 JavaBeans 机制(Spring 使用)完全忽略了字段。
    • @SeanPatrickFloyd:我相信答案的意思是“XML 中给出的属性名称被翻译成一个 setter 名称”(翻译是添加“set”前缀)。就像那样,它实际上是正确的。
    猜你喜欢
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 2019-03-09
    相关资源
    最近更新 更多