在春天访问AOP代理的最佳方式是什么?

时间:2015-04-08 01:59:48

标签: spring proxy aop

由于Spring实施了AOP,有时候你想要在同一个班级中调用一个方法来调用你的建议。

这是一个简单的例子

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

现在忽略一下,在春天我可以使用@Cached注释进行缓存,我的例子的一点是getSomeValue()被其他bean通过spring代理访问并运行相关的建议。对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中查找我的代理对象。丑陋,我知道。任何关于更清洁的方法的建议都会很好。

1 个答案:

答案 0 :(得分:1)

您可以使用@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无效。