Spring bean如何检测它本身是否已包装在AOP代理中?

Gra*_*ray 8 java proxy aop spring

每当执行标记有注释的DAO方法时,我们都使用Spring TransactionInterceptor来设置一些数据库分区信息.我们需要它能够将查询路由到不同的数据库分区.ThreadLocal@Transactional

这适用于大多数DAO方法:

// this causes the invoke method to set a thread-local with the host name of
// the database server the partition is on
@Transactional
public int deleteAll() throws LocalDataException {
Run Code Online (Sandbox Code Playgroud)

问题是我们需要在DAO中引用DAO 代理对象本身.通常我们必须在proxy-dao中传递调用者:

public Pager<Foo, Long> getPager(FooDao proxyDao) {
Run Code Online (Sandbox Code Playgroud)

这看起来像代码中的以下内容显然是粗略的.

fooDao.getPager(fooDao);
Run Code Online (Sandbox Code Playgroud)

问题是,当我们FooDao的里面,this不是我们所需要的代理DAO.

是否有更好的机制让bean发现它周围有代理包装器?我看过Spring AOPUtils,但我看不到找到对象的代理.我不想要isAopProxy(...)例如.我还阅读了Spring AOP文档,但除非我实现自己希望避免的AOP本机代码,否则我无法在那里看到解决方案.

我怀疑我可以使用ApplicationContextAware实用程序bean和setProxyDao(...)方法将DAO注入其自身,但这似乎也是一种黑客攻击.我可以检测代理的任何其他想法,以便我可以在bean本身内使用它吗?谢谢你的帮助.

Bij*_*men 6

考虑到AspectJ编译时间或加载时间编织对你来说,这是一个与你所建议的一致的hacky解决方案:

沿着这些方向创建一个界面:

public interface ProxyAware<T> {
    void setProxy(T proxy);
}
Run Code Online (Sandbox Code Playgroud)

让你的Dao实现ProxyAware实现,现在创建一个带有Ordered接口的BeanPostProcessor,最后运行,沿着这些方向:

public class ProxyInjectingBeanPostProcessor implements BeanPostProcessor, Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (AopUtils.isAopProxy((bean))){
            try {
                Object target = ((Advised)bean).getTargetSource().getTarget();
                if (target instanceof ProxyAware){
                    ((ProxyAware) target).setProxy(bean);
                }
            } catch (Exception e) {
                // ignore
            }
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
Run Code Online (Sandbox Code Playgroud)

它很难看,但很有效.