Spring - Unterbrechen der Bean-Erstellung und Injizieren eines benutzerdefinierten Proxys
Ich habe ein@Controller
mit@Autowired
Felder und Handlermethoden, die mit benutzerdefinierten Anmerkungen versehen werden sollen.
Zum Beispiel,
@Controller
public class MyController{
@Autowired
public MyDao myDao;
@RequestMapping("/home")
@OnlyIfXYZ
public String onlyForXYZ() {
// do something
return "xyz";
}
}
Woher@OnlyIfXYZ
ist ein Beispiel für eine benutzerdefinierte Anmerkung. Ich dachte, ich würde die Erstellung des Controller-Beans abfangen und meinen eigenen CGLIB-Proxy übergeben, auf den Spring dann Eigenschaften wie das automatisch verdrahtete Feld festlegen kann.
Ich habe versucht mit einemInstantiationAwareBeanPostProcessor
Aber diese Lösung funktioniert nicht gut, weilpostProcessBeforeInstantiation()
schließt den Rest des Prozesses kurz. Ich habe es mit versuchtpostProcessAfterInitialization()
, Wie unten
public class MyProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// Here the bean autowired fields are already set
return bean;
}
@Override
public Object postProcessAfterInitialization(Object aBean, String aBeanName) throws BeansException {
Class<?> clazz = aBean.getClass();
// only for Controllers, possibly only those with my custom annotation on them
if (!clazz.isAnnotationPresent(Controller.class))
return aBean;
Object proxy = Enhancer.create(clazz, new MyMethodInterceptor());
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
try {
// get the field and copy it over to the proxy
Object objectToCopy = field.get(aBean);
field.set(proxy, objectToCopy);
} catch (IllegalArgumentException | IllegalAccessException e) {
return aBean;
}
}
return proxy;
}
}
Diese Lösung verwendet Reflection, um alle Felder der Ziel-Bean in die Proxy-Bean zu kopieren (für meinen Geschmack eine Art Hacky). Ich habe aber keinen Zugang zumHttpServletRequest
undHttpServletResponse
Objekte, wenn dies keine Argumente in der Methode sind, die ich abfange.
Gibt es einen weiteren Rückruf, den ich in die Spring-Bean-Erstellungslogik einfügen kann, um meinen eigenen Proxy-Controller einzufügen, bevor Spring seine Eigenschaften auffüllt?Ich muss in der Lage sein, auf das Internet zuzugreifenHttpServletRequest
undHttpServletResponse
Objekte, unabhängig davon, ob die Controller-Handler-Methode dies in ihrer Definition hat, dh. als Argumente.
N.B Das@Autowired
Feld ist auch ein Proxy, mit dem es kommentiert ist@Transactional
also macht Spring alles klar.
BEARBEITEN: Die AOP-Lösung funktioniert gut zum Abfangen des Methodenaufrufs, aber ich kann keine Möglichkeit finden, auf die zuzugreifenHttpServletRequest
undHttpServletResponse
Objekte, wenn sie nicht bereits Methodenargumente sind.
Ich werde wahrscheinlich HandlerInterceptorAdapter verwenden, aber ich hatte gehofft, ich kann es mit OOP tun, um den Overhead nicht zu Methoden hinzuzufügen, die es nicht benötigen.