7

我想知道是否有办法将spring bean的属性绑定到另一个bean的属性,所以如果在运行时绑定属性发生任何变化,我期望引用bean的属性也会发生变化。我会用一个小代码片段来解释更多。

<bean id="johnHome" class="example.Contact">
    <property name="电话" value="5551333" />
</豆>

<bean id="johnWork" class="example.Contact">
    <属性名称="电话">
        <util:property-path path="johnHome.phone" />
    </属性>
</豆>

好的。这适用于初始 bean 接线,但我真正想要的是绑定属性,因此如果属性在运行时发生更改,引用 bean 也会更改。如果我想用一个比喻来展示它会看起来像这样。

<bean id="johnHome" class="example.Contact">
    <property name="电话" value="5551333" />
</豆>

<bean id="johnWork" class="example.Contact">
    <属性名称="电话">
        <util:bind path="johnHome.phone" />
    </属性>
</豆>

我是否过多地超载了弹簧的概念,或者这是否可能没有很多技巧?

谢谢..

4

4 回答 4

1

最简单的方法 - 使该属性成为由其他两个 bean 引用的 bean,例如,对于 String 值具有 StringHolder 类:

public class StringHolder {
     private String value;

     // setter and getter elided due to author's lazyness

}
于 2009-06-01T21:48:17.213 回答
1

Spring 背后的整个想法是(曾经?)保持由普通的旧 java 对象组成的干净的面向对象设计,并使用 spring 框架来处理繁琐的对象创建。至于 AOP,这应该只处理横切关注点。我完全不相信这是 AOP 是一个好主意的情况之一。您的应用程序依赖于这些电话号码相互同步的行为,这是主要功能之一。因此,您的设计应该反映这一点。

处理此特定问题的最合乎逻辑的方法可能是将电话号码设为自己的类(如果您想区分不同类型的电话号码,这也很方便)。

如果您有一个将数字作为构造函数参数的 PhoneNumber 对象,则映射变得微不足道:

<bean id="johnFirstPhone" class="example.PhoneNumber">
  <constructor-arg value="5551333" />
</bean>

<bean id="johnHome" class="example.Contact">
  <property name="phone" ref="johnFirstPhone" />
</bean>

<bean id="johnWork" class="example.Contact">
  <property name="phone" ref="johnFirstPhone" />
</bean>

当然,您是否将其映射到静态文件中是另一回事,但在这种情况下,您显然只需要一个引用/指针。

于 2009-07-01T13:47:12.570 回答
0

我认为你在 Spring 2.5 中做的事情是不可能的。在Spring 3 中使用新的表达式语法可能是可能的,但我不这么认为。

即使是这样,我想也会令人困惑。最好将您的共享值粘贴到它自己的类中,并将该类的实例注入需要共享它的其他 bean。

于 2009-05-21T15:01:30.587 回答
0

我能想到两种可能。

一个是(这是一种 hack),如果您没有很多 bean 需要像示例中的那样链接,您可以将 johnWork 注入 johnHome bean,并在 johnHome.setPhone 中更新johnWork 电话属性,例如:

public class Contact {
    private Contact myWorkContact;
    private String phone;

    public void setPhone(String phone) {
        this.phone = phone;
        if (this.myWorkContact != null) {
            this.myWorkContact.setPhone(phone);
        }
    }

    public void setWorkContact(Contact c) {
        this.myWorkContact = c;
    }
}

或者您可以让 HomeContact 和 WorkContact 都扩展一个类 Contact 并对其进行相同的注入。

如果您有大量需要这个的bean(例如,如果您的应用程序实际上正在处理联系信息),那么使用AOP(对于给出的示例,您将需要AspectJ)我认为您可以做这样的事情(它将是如果您获得大量对象,则会占用大量内存,但您可以看到类似的东西是如何工作的):

警告:这实际上很快就变得复杂了,但我很确定在你解决了一些问题之后它会起作用

public class Contact {
    ...

    private String phone;
    private String name;
    private Integer id;

    public Contact(Integer id, String name, String phone) {
        this.phone = phone;
        this.name = name;
        this.id = id;
    }

    public void setPhone(String phone) {
        this.phone = phone.
    }

    //Other getters, setters, etc

    ...
}


@Aspect
public class ContactPhoneSynchronizer {
    //there is probably a more efficient way to keep track of contact objects
    //but right now i can't think of one, because for things like a tree, we need to 
    //be able to identify objects with the same name (John Smith), but that
    //have different unique ids, since we only want one of each Contact object
    //in this cache.

    private List<Contact> contacts = Collections.synchronizedList(new ArrayList<Contact>());

    /**
        This method will execute every time someone makes a new Contact object.
        If it already exists, return it from the cache in this.contacts.  Otherwise,
        proceed with the object construction and put that object in the cache.
    **/

    @Around("call(public Contact.new(Integer,String,String)) && args(id,name,phone)")
    public Object cacheNewContact(ProceedingJoinPoint joinPoint, Integer id, String name, String phone) {
        Contact contact = null;

        for (Contact c : contacts) {
            if (id.equals(c.getId()) {
                contact = c;
                break;
            }
        }

        if (contact == null) {
            contact = (Contact) joinPoint.proceed();
            this.contacts.add(contact);            
        }

        return contact;
    }

    /**This should execute every time a setPhone() method is executed on 
        a contact object.  The method looks for all Contacts of the same
        name in the cache and then sets their phone number to the one being passed
        into the original target class.

        Because objects are passed by reference until you do a reassociation, 
        calling c.setPhone on the object in the cache should update the actual
        instance of the object in memory, so whoever has that reference will
        get the updated information.
    **/

    @After("execution(example.Contact.setPhone(String) && args(phone)")
    public void syncContact(JoinPoint joinPoint, String phone) {
        Contact contact = joinPoint.getTarget();

        for (Contact c : this.contacts) {
            if (c.getName().equals(contact.getName()) {
                c.setPhone(phone);
            }
        }
    }
}

同样,可能有 100 种方法可以优化它,因为我是在脑海中输入它;也就是说,如果你一开始就想走这条路。理论上它应该可以工作,但我根本没有测试过。

总之,春节快乐!

于 2009-06-01T21:28:59.403 回答