考虑一个InventoryService接口:
public interface InventoryService{public Inventory create(Inventory inventory);public List<Inventory> list();public Inventory findByVin(String vin);public Inventory update(Inventory inventory);public boolean delete(Long id);public Inventory compositeUpdateService(String vin, String newMake);
}
还请考虑该服务的默认实现,并假设最后一个方法CompositeUpdateService内部在Bean本身上调用两个方法,如下所示:
public Inventory compositeUpdateService(String vin, String newMake) {logger.info("composite Update Service called");Inventory inventory = this.findByVin(vin);inventory.setMake(newMake);this.update(inventory);return inventory;
}
如果我现在创建一个方面来建议对InventoryService的任何调用,以跟踪每个方法调用花费的时间,Spring AOP将为InventoryService bean创建一个动态代理:
但是,对CompositeUpdateService的调用将仅在此方法的级别上记录时间,即CompositeUpdateService内部对findByVin的调用,update绕过了代理,因此不会被跟踪:
一个好的解决方法是使用AspectJ的全部功能– AspectJ会更改DefaultInventoryService的所有方法的字节码,以包括对建议的调用。
我们制定的解决方法是将对代理本身的引用注入到bean中,而不是调用this.findByVin和this.update,而是调用proxy.findByVin和proxy.update!
因此,现在我们如何将对代理的引用干净地注入到bean中-我提供的解决方案是创建一个接口,以标记对自己的代理感兴趣的bean:
public interface ProxyAware<T> {void setProxy(T proxy);
}
感兴趣的接口及其实现如下所示:
public interface InventoryService extends ProxyAware<InventoryService>{
...
}public class DefaultInventoryService implements InventoryService{ ...private InventoryService proxy;@Overridepublic void setProxy(InventoryService proxy) {this.proxy = proxy;}
}
然后定义一个BeanPostProcessor注入这个代理!
public class ProxyInjectingBeanPostProcessor implements BeanPostProcessor, Ordered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (AopUtils.isAopProxy((bean))){try {Object target = ((Advised)bean).getTargetSource().getTarget();if (target instanceof ProxyAware){((ProxyAware) target).setProxy(bean);}} catch (Exception e) {return bean;}}return bean;}@Overridepublic int getOrder() {return Integer.MAX_VALUE;}
}
不是最干净的实现,但是可以!
参考: http : //blog.springsource.org/2012/05/23/understanding-proxy-usage-in-spring/
参考: all和杂项博客中, JCG合作伙伴 Biju Kunjummen 引用了代理课程中的动态代理 。
翻译自: https://www.javacodegeeks.com/2012/07/reference-to-dynamic-proxy-in-proxied.html