Due to Spring's implementation of AOP there are times when you want to call a method within the same class where you'd like the call to pass through your advice.
Here's a quick example
@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
}
}
Now ignore for a second that in spring I could use @Cached annotations for caching, the point of my example is that getSomeValue() is accessed by other beans passing through the spring proxy and running the associated advice. The internal call to txnGetSomeValue will not and in my example will miss having the advice we apply at the @Transactional point cut.
What's the best way to get access to your proxy so you can apply the advice?
My best approach works, but is clumsy. It heavily exposes the implementation. I figured this out years ago and have just stuck with this awkward code but would like to know what is the preferred method. My hacky approach looks like this.
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;
}
}
What I've done is add BeanNameAware and SpringContextAware so that I can look up my proxy object in Spring. Ugly I know. Any advice on a cleaner way to do this would be nice.
Aucun commentaire:
Enregistrer un commentaire