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.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage