我有一个字段和@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)。但是,如果这些不是我正在拦截的方法中的参数,我将无权访问HttpServletRequestand对象。HttpServletResponse
在 Spring 填充其属性之前,我是否可以将另一个回调注入到 Spring bean 创建逻辑中以注入我自己的代理控制器?无论控制器处理程序方法是否在其定义中包含它,我都需要能够访问HttpServletRequestand对象,即。HttpServletResponse作为论据。
NB该@Autowired字段也是一个代理,它带有注释,@Transactional因此 Spring 代理它。
编辑: AOP 解决方案可以很好地拦截方法调用,但是如果它们还不是方法参数,我找不到访问HttpServletRequestand对象的方法。HttpServletResponse
我可能最终会使用 HandlerInterceptorAdapter,但我希望我可以使用 OOP 来做到这一点,以免给不需要它的方法增加开销。