在 spring 中访问 AOP 代理的最佳方式是什么?

What's the best way to access your AOP proxy in spring?

由于 Spring 的 AOP 实现,有时您想要在同一个 class 中调用方法,您希望调用通过您的建议。

这是一个简单的例子

@Service
public class SomeDaoClass {
    public int getSomeValue() {
        // do some cache look up
        Integer cached = ...;
        if ( cached == null ) {
            cached = txnGetSomeValue();
            // store in cache
        }

        return cached;
    }

    @Transactional
    public int txnGetSomeValue() {
        // look up in database
    }
}

现在暂时忽略 spring 中我可以使用 @Cached 注释进行缓存,我的示例的要点是 getSomeValue() 被其他通过 spring 代理的 bean 访问和 运行 相关的建议。对 txnGetSomeValue 的内部调用不会,在我的示例中将错过我们在 @Transactional 切点处应用的建议。

获得代理访问权以便采纳建议的最佳方式是什么?

我最好的方法可行,但很笨拙。它严重暴露了实现。我几年前就想通了,只是坚持使用这个笨拙的代码,但想知道首选方法是什么。我的 hacky 方法看起来像这样。

public interface SomeDaoClass {
    public int getSomeValue();

    // sometimes I'll put these methods in another interface to hide them
    // but keeping them in the primary interface for simplicity.
    public int txnGetSomeValue();
}

@Service
public class SomeDaoClassImpl implements SomeDaoClass, BeanNameAware, ApplicationContextAware {
    public int getSomeValue() {
        // do some cache look up
        Integer cached = ...;
        if ( cached == null ) {
            cached = proxy.txnGetSomeValue();
            // store in cache
        }

        return cached;
    }

    @Transactional
    public int txnGetSomeValue() {
        // look up in database
    }

    SomeDaoClass proxy = this;
    String beanName = null;
    ApplicationContext ctx = null;

    @Override
    public void setBeanName(String name) {
        beanName = name;
        setProxy();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
        setProxy();
    }

    private void setProxy() {
        if ( beanName == null || ctx == null )
            return;

        proxy = (BlockDao) ctx.getBean(beanName);

        beanName = null;
        ctx = null;
    }
}

我所做的是添加 BeanNameAware 和 SpringContextAware,以便我可以在 Spring 中查找我的代理对象。丑我知道。任何关于更清洁的方法的建议都会很好。

您可以使用 @Resource

注入代理
@Service
public class SomeDaoClassImpl implements SomeDaoClass {

    @Resource
    private SomeDaoClassImpl someDaoClassImpl;

    public int getSomeValue() {
        // do some cache look up
        Integer cached = ...;
        if ( cached == null ) {
            cached = somDaoClassImpl.txnGetSomeValue();
            // store in cache
        }

        return cached;
    }

    @Transactional
    public int txnGetSomeValue() {
        // look up in database
    }

注意@Autowired将不起作用。