在 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
将不起作用。
由于 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
将不起作用。