Spring - Interceptar la creación de beans e inyectar proxy personalizado
tengo un@Controller
con@Autowired
campos y métodos de manejo que quiero anotar con anotaciones personalizadas.
Por ejemplo,
@Controller
public class MyController{
@Autowired
public MyDao myDao;
@RequestMapping("/home")
@OnlyIfXYZ
public String onlyForXYZ() {
// do something
return "xyz";
}
}
Dónde@OnlyIfXYZ
Es un ejemplo de una anotación personalizada. Estaba pensando que interceptaría la creación del bean Controller, pasaría mi propio proxy CGLIB en el que Spring puede establecer propiedades, como el campo autowired.
Traté de usar unInstantiationAwareBeanPostProcessor
pero esa solución no funciona muy bien porquepostProcessBeforeInstantiation()
Cortocircuita el resto del proceso. Lo intenté conpostProcessAfterInitialization()
, como abajo
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;
}
}
Esta solución utiliza la reflexión para copiar todos los campos del bean objetivo al proxy (tipo de hacky a mi gusto). Pero no tengo acceso a laHttpServletRequest
yHttpServletResponse
Objetos si esos no son argumentos en el método que estoy interceptando.
¿Hay otra devolución de llamada que pueda inyectar en la lógica de creación del bean Spring para inyectar mi propio Proxy Controller antes de que Spring complete sus propiedades?Necesito poder acceder a laHttpServletRequest
yHttpServletResponse
objetos independientemente de si el método del controlador del controlador lo tiene en su definición, es decir. como argumentos
NÓTESE BIEN los@Autowired
El campo también es un proxy, se anota con@Transactional
Así que la primavera lo apunta.
EDITAR: La solución AOP funciona bien para interceptar la invocación del método, pero no puedo encontrar una manera de acceder alHttpServletRequest
yHttpServletResponse
Objetos, si no son ya argumentos de método.
Probablemente voy a usar HandlerInterceptorAdapter, pero esperaba poder hacerlo con OOP para no agregar la sobrecarga a los métodos que no lo necesitan.