Spring - Intercepting bean creation and injecting custom proxy
java, spring, spring-aop, spring-mvc
Solution
Taking into account your comment under the question all you need is HandlerInterceptor.
http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/HandlerInterceptor.html
You need to implement that interface and add it to your configuration, for example:
<mvc:interceptors>
<bean id="customInterceptor" class="com.example.interceptors.CustomInterceptor"/>
</mvc:interceptors>
This interface provides method preHanlde, which has request, response and HandlerMethod. To check if the method is annotated just try this:
HandlerMethod method = (HandlerMethod) handler;
OnlyIfXYZ customAnnotation = method.getMethodAnnotation(OnlyIfXYZ.class);
Problem
I have a `@Controller` with `@Autowired` fields and handler methods that I want to annotate with custom annotations. For example, ``` @Controller public class MyController{ @Autowired public MyDao myDao; @RequestMapping("/home") @OnlyIfXYZ public String onlyForXYZ() { // do something return "xyz"; } } ``` Where `@OnlyIfXYZ` is an example of a custom annotation. I was thinking I would intercept the Controller bean creation, pass my own CGLIB proxy on which Spring can then set properties, like the autowired field. I tried using a `InstantiationAwareBeanPostProcessor` but that solution doesn't work great because `postProcessBeforeInstantiation()` short-circuits the rest of the process. I tried with `postProcessAfterInitialization()`, like below ``` 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; } } ``` This solution uses reflection to copy over all the fields of the target bean to the proxy bean (kind of hacky for my taste). But I don't have access to the `HttpServletRequest` and `HttpServletResponse` objects if those aren't arguments in the method I'm intercepting. Is there another callback I can inject into Spring bean creation logic to inject my own Proxy Controller before Spring populates its properties? I need to be able to access the `HttpServletRequest` and `HttpServletResponse` objects regardless of if the Controller handler method has it in its definition, ie. as arguments. N.B The `@Autowired` field is also a proxy, it is annotated with `@Transactional` so Spring proxies it up. EDIT: The AOP solution works nicely for intercepting the method invocation, but I can't find a way to access the `HttpServletRequest` and `HttpServletResponse` objects, if they aren't already method arguments. I'm probably going to end up using HandlerInterceptorAdapter, but I was hoping I can do it with OOP so as to not add the overhead to methods that don't need it.