Я могу придумать две возможности.
Один из них (это своего рода хак), если у вас не так много бинов, которые должны быть связаны, как в вашем примере, вы можете добавить johnWork в bean-компонент johnHome, и в 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 способов, которыми вы могли бы оптимизировать это, так как я набираю это на макушке; то есть, если вы хотели пойти по этому маршруту в первую очередь. Теоретически это должно работать, но я его вообще не проверял.
Во всяком случае, счастливой весны!