|
23 | 23 | import java.util.concurrent.*; |
24 | 24 | import java.util.function.*; |
25 | 25 |
|
| 26 | +/** |
| 27 | + * TODO: |
| 28 | + * - More Tests |
| 29 | + * - Document |
| 30 | + * - singletonBeans |
| 31 | + * - bcs |
| 32 | + */ |
26 | 33 | public class BeanRegistryImplementation implements BeanRegistry, BeanCollector { |
27 | 34 |
|
28 | 35 | private static final Logger log = LoggerFactory.getLogger(BeanRegistryImplementation.class); |
@@ -85,38 +92,51 @@ public void handle(ChangeEvent changeEvent, boolean isLast) { |
85 | 92 | } |
86 | 93 |
|
87 | 94 | private void activationRun() { |
88 | | - Set<UidAction> uidsToRemove = new HashSet<>(); |
89 | | - for (UidAction uidAction : uidsToActivate) { |
| 95 | + for (UidAction uidAction : cloneUidActions()) { |
90 | 96 | BeanContainer bc = bcs.get(uidAction.uid); |
91 | | - try { |
92 | | - Object bean = define(bc.getDefinition()); |
93 | | - bc.setSingleton(bean); |
| 97 | + if (bc == null) { |
| 98 | + log.warn("Skipping activation for missing uid {}", uidAction.uid); |
| 99 | + continue; |
| 100 | + } |
94 | 101 |
|
95 | | - // e.g. inform router about new proxy |
96 | | - observer.handleBeanEvent(new BeanDefinitionChanged(uidAction.action, bc.getDefinition()), bean, getOldBean(uidAction.action, bc.getDefinition())); |
| 102 | + BeanDefinition def = bc.getDefinition(); |
| 103 | + Object oldBean = getOldBean(uidAction.action, uidAction.uid); // capture first |
| 104 | + Object newBean = null; // Do not inline! |
97 | 105 |
|
98 | | - if (uidAction.action.isAdded() || uidAction.action.isModified()) |
99 | | - singletonBeans.put(bc.getDefinition().getUid(), bean); |
| 106 | + try { |
100 | 107 | if (uidAction.action.isDeleted()) { |
101 | | - singletonBeans.remove(bc.getDefinition().getUid()); |
102 | | - bcs.remove(bc.getDefinition().getUid()); |
| 108 | + singletonBeans.remove(uidAction.uid); |
| 109 | + bcs.remove(uidAction.uid); |
| 110 | + } else { |
| 111 | + newBean = define(def); |
| 112 | + bc.setSingleton(newBean); |
| 113 | + singletonBeans.put(uidAction.uid, newBean); |
103 | 114 | } |
104 | | - uidsToRemove.add(uidAction); |
| 115 | + |
| 116 | + observer.handleBeanEvent( |
| 117 | + new BeanDefinitionChanged(uidAction.action, def), |
| 118 | + newBean, |
| 119 | + oldBean |
| 120 | + ); |
105 | 121 | } catch (Exception e) { |
106 | | - log.error("Could not handle {} {}/{}", uidAction.action, |
107 | | - bc.getDefinition().getNamespace(), bc.getDefinition().getName(), e); |
| 122 | + log.error("Could not handle {} {}/{}", uidAction.action, def.getNamespace(), def.getName(), e); |
108 | 123 | throw new RuntimeException(e); |
109 | 124 | } |
110 | 125 | } |
111 | | - for (UidAction uidAction : uidsToRemove) |
112 | | - uidsToActivate.remove(uidAction); |
113 | 126 | } |
114 | 127 |
|
115 | | - private @Nullable Object getOldBean(WatchAction action, BeanDefinition bd) { |
116 | | - Object oldBean = null; |
117 | | - if (action.isModified() || action.isDeleted()) |
118 | | - oldBean = singletonBeans.get(bd.getUid()); |
119 | | - return oldBean; |
| 128 | + private @NotNull List<UidAction> cloneUidActions() { |
| 129 | + // Iterate safely over synchronizedSet |
| 130 | + final List<UidAction> actions; |
| 131 | + synchronized (uidsToActivate) { |
| 132 | + actions = new ArrayList<>(uidsToActivate); |
| 133 | + uidsToActivate.clear(); |
| 134 | + } |
| 135 | + return actions; |
| 136 | + } |
| 137 | + |
| 138 | + private @Nullable Object getOldBean(WatchAction action, String uid) { |
| 139 | + return (action.isModified() || action.isDeleted()) ? singletonBeans.get(uid) : null; |
120 | 140 | } |
121 | 141 |
|
122 | 142 | @Override |
|
0 commit comments