Spring - 拦截bean创建和注入自定义代理 [英] Spring - Intercepting bean creation and injecting custom proxy

查看:490
本文介绍了Spring - 拦截bean创建和注入自定义代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 @Controller ,带有 @Autowired 字段和处理程序方法,我想用自定义注释进行注释。

I have a @Controller with @Autowired fields and handler methods that I want to annotate with custom annotations.

例如,

@Controller
public class MyController{
    @Autowired
    public MyDao myDao;

    @RequestMapping("/home")
    @OnlyIfXYZ
    public String onlyForXYZ() {
        // do something
        return "xyz";
    }
}

其中 @OnlyIfXYZ 是自定义注释的示例。我以为我会拦截Controller bean创建,传递我自己的CGLIB代理,Spring可以在其上设置属性,比如autowired字段。

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.

我尝试使用 InstantiationAwareBeanPostProcessor 但该解决方案效果不佳,因为 postProcessBeforeInstantiation()会使进程的其余部分短路。我尝试使用 postProcessAfterInitialization(),如下所示

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;
    }
}

此解决方案使用反射复制所有字段目标bean到代理bean(对我来说有点hacky)。但我没有访问 HttpServletRequest HttpServletResponse 对象,如果这些对象不是方法I'中的参数拦截。

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.

我是否可以在Spring填充其属性之前注入Spring bean创建逻辑以注入我自己的代理控制器? 我需要能够访问 HttpServletRequest HttpServletResponse 对象,无论Controller处理程序方法是否具有它在其定义中,即。作为参数。

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.

NB @Autowired 字段也是一个代理,它用 @Transactional 注释,所以Spring代理它。

N.B The @Autowired field is also a proxy, it is annotated with @Transactional so Spring proxies it up.

编辑: AOP解决方案可以很好地拦截方法调用,但我找不到一种方法来访问 HttpServletRequest HttpServletResponse 对象,如果它们不是方法参数。

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.

我可能最终会使用HandlerInterceptorAdapter,但我希望我能用OOP这样做至于不向不需要它的方法增加开销。

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.

推荐答案

考虑到你在所有问题下的评论需要是HandlerInterceptor。

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>

此接口提供方法preHanlde,它具有请求,响应和HandlerMethod。要检查方法是否已注释,请尝试以下操作:

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);

这篇关于Spring - 拦截bean创建和注入自定义代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆