我有一个字段和@Controller
处理@Autowired
程序方法,我想用自定义注释进行注释。
例如,
@Controller
public class MyController{
@Autowired
public MyDao myDao;
@RequestMapping("/home")
@OnlyIfXYZ
public String onlyForXYZ() {
// do something
return "xyz";
}
}
哪里@OnlyIfXYZ
是自定义注释的示例。我在想我会拦截Controller bean的创建,传递我自己的CGLIB代理,然后Spring可以在其上设置属性,比如自动装配字段。
我尝试使用 aInstantiationAwareBeanPostProcessor
但该解决方案效果不佳,因为postProcessBeforeInstantiation()
会使其余过程短路。我试过了postProcessAfterInitialization()
,如下所示
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;
}
}
该解决方案使用反射将目标 bean 的所有字段复制到代理 bean(对我来说有点 hacky)。但是,如果这些不是我正在拦截的方法中的参数,我将无权访问HttpServletRequest
and对象。HttpServletResponse
在 Spring 填充其属性之前,我是否可以将另一个回调注入到 Spring bean 创建逻辑中以注入我自己的代理控制器?无论控制器处理程序方法是否在其定义中包含它,我都需要能够访问HttpServletRequest
and对象,即。HttpServletResponse
作为论据。
NB该@Autowired
字段也是一个代理,它带有注释,@Transactional
因此 Spring 代理它。
编辑: AOP 解决方案可以很好地拦截方法调用,但是如果它们还不是方法参数,我找不到访问HttpServletRequest
and对象的方法。HttpServletResponse
我可能最终会使用 HandlerInterceptorAdapter,但我希望我可以使用 OOP 来做到这一点,以免给不需要它的方法增加开销。