内容简介:山有木兮木有枝,心悦君兮君不知。到目前位置,关于
山有木兮木有枝,心悦君兮君不知。
概述
到目前位置,关于 aop
的部分,我们已经完成了以下功能
- 根据
Bean
的名称和方法名,获取Method
对象。MethodLocatingFactory
- 给定一个类的方法,判断该方法是否符合
Pointcut
的表达式。AspectJExpressionPointcut
- 实现了前置,后置和异常的通知。
AspectJBeforeAdvice
,AspectJAfterReturningAdvice
,AspectJAfterThrowingAdvice
- 实现了
Advice
按次续依次执行。ReflectiveMethodInvocation
- 给定一个
AopConif
,使用Cglib
生成一个对象的代理。
接下来只剩下最后一个工作,读取 bean-v5.xml
创建 BeanDefinition
。
分析aop:config标签
在创建 BeanDefinition
之前我们先看一下 aop:config
的定义,之前 Bean
的定义。
<bean id = "nioCoder" class = "com.niocoder.service.v1.NioCoderService"> </bean>
现在 Bean
的定义
<!-- aop 配置--> <aop:config> <!-- aop 核心配置 依赖tx--> <aop:aspect ref="tx"> <!-- 切入点配置 包下面的placeOrder 方法--> <aop:pointcut id="placeOrder" expression="execution(* com.niocoder.service.v5.*.placeOrder(..))"/> <!-- 通知配置,--> <aop:before pointcut-ref="placeOrder" method="start"/> <aop:after-returning pointcut-ref="placeOrder" method="commit"/> <aop:after-throwing pointcut-ref="placeOrder" method="rollback"/> </aop:aspect> </aop:config>
之前如果 Bean
有其它额外的属性,我们都是通过 PropertyValue
或 ConstructorArgument
来表示。但 aop:config
的标签该如何表达呢?
spring
还是通过 GenericBeanDefinition
来表示 aop:config
标签,关于标签属性的映射,参考下图
<aop:pointcut id="placeOrder" expression="execution(* com.niocoder.service.v5.*.placeOrder(..))"/>
<aop:before pointcut-ref="placeOrder" method="start"/>
通过上图的构造器类型,我们发现这与我们之前创建 AspectJBeforeAdvice
的构造器参数不匹配。
public AspectJBeforeAdvice(Method adviceMethod, AspectJExpressionPointcut pointcut, Object adviceObject) { super(adviceMethod, pointcut, adviceObject); }
因上图的第一个构造器参数中含有 methodName
,所以我们只需将修改 adviceObject
修改为 AspectInstanceFactory
。关于 AspectInstanceFactory
的类图设计如下:
FactoryBean
工厂bean,
/** * 工厂bean * @author zhenglongfei */ public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); }
BeanFactoryAware
有些实现类需要用到 BeanFactory
,实现该接口即可。
public interface BeanFactoryAware { /** * set beanFactory * * @param beanFactory * @throws BeansException */ void setBeanFactory(BeanFactory beanFactory) throws BeansException; }
AspectInstanceFactory
/** * @author zhenglongfei */ public class AspectInstanceFactory implements BeanFactoryAware { private String aspectBeanName; private BeanFactory beanFactory; public void setAspectBeanName(String aspectBeanName) { this.aspectBeanName = aspectBeanName; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; if (!StringUtils.hasText(this.aspectBeanName)) { throw new IllegalArgumentException(" 'aspectBeanName' is required"); } } public Object getAspectInstance() throws Exception { return this.beanFactory.getBean(this.aspectBeanName); } }
MethodLocatingFactory
实现 FactoryBean<Method>
和 BeanFactoryAware
public class MethodLocatingFactory implements FactoryBean<Method>, BeanFactoryAware { }
AbstractAspectJAdvice
将 Object adviceObject
替换成 AspectInstanceFactory adviceObjectFactory
,修改 invokeAdviceMethod()
方法,对象是从 benFactory
中根据 aspectBeanName
获取。
ublic abstract class AbstractAspectJAdvice implements Advice { private Method adviceMethod; private AspectJExpressionPointcut pointcut; private Object adviceObject; public AbstractAspectJAdvice(Method adviceMethod, AspectJExpressionPointcut pointcut, Object adviceObject) { this.adviceMethod = adviceMethod; this.pointcut = pointcut; this.adviceObject = adviceObject; } @Override public Pointcut getPointcut() { return pointcut; } public Method getAdviceMethod() { return this.adviceMethod; } public void invokeAdviceMethod() throws Throwable { adviceMethod.invoke(adviceObject); } }
AspectJBeforeAdvice
因抽象方法修改,子类构造函数也需要修改, AspectJAfterReturningAdvice
和 AspectJAfterThrowingAdvice
也需要修改
ublic class AspectJBeforeAdvice extends AbstractAspectJAdvice { public AspectJBeforeAdvice(Method adviceMethod, AspectJExpressionPointcut pointcut, Object adviceObject) { super(adviceMethod, pointcut, adviceObject); } ...... }
AbstractV5Test
提出公工方法到一个测试类中
public class AbstractV5Test { protected BeanFactory getBeanFactory(String configFile) { DefaultBeanFactory defaultBeanFactory = new DefaultBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(defaultBeanFactory); reader.loadBeanDefinition(new ClassPathResource(configFile)); return defaultBeanFactory; } protected Method getAdviceMethod(String methodName) throws Exception { return TransactionManager.class.getMethod(methodName); } protected AspectInstanceFactory getAspectInstanceFactory(String targetBeanName) { AspectInstanceFactory factory = new AspectInstanceFactory(); factory.setAspectBeanName(targetBeanName); return factory; } }
CglibAopProxyTest
动态获取 AspectInstanceFactory
public class CglibAopProxyTest extends AbstractV5Test { private static AspectJBeforeAdvice beforeAdvice = null; private static AspectJAfterReturningAdvice afterAdvice = null; private AspectJExpressionPointcut pc = null; private BeanFactory beanFactory = null; private NioCoderService nioCoderService = null; private AspectInstanceFactory aspectInstanceFactory = null; @Before public void setUp() throws Exception { MessageTracker.clearMsgs(); String expression = "execution(* com.niocoder.service.v5.*.placeOrder(..))"; pc = new AspectJExpressionPointcut(); pc.setExpression(expression); nioCoderService = new NioCoderService(); beanFactory = this.getBeanFactory("bean-v5.xml"); aspectInstanceFactory = this.getAspectInstanceFactory("tx"); aspectInstanceFactory.setBeanFactory(beanFactory); beforeAdvice = new AspectJBeforeAdvice( getAdviceMethod("start"), pc, aspectInstanceFactory); afterAdvice = new AspectJAfterReturningAdvice( getAdviceMethod("commit"), pc, aspectInstanceFactory); } @Test public void testGetProxy() { AopConfig config = new AopConfigSupport(); config.addAdvice(beforeAdvice); config.addAdvice(afterAdvice); config.setTargetObject(nioCoderService); CglibProxyFactory proxyFactory = new CglibProxyFactory(config); NioCoderService proxy = (NioCoderService) proxyFactory.getProxy(); proxy.placeOrder(); List<String> msgs = MessageTracker.getMsgs(); Assert.assertEquals(3, msgs.size()); Assert.assertEquals("start tx", msgs.get(0)); Assert.assertEquals("place order", msgs.get(1)); Assert.assertEquals("commit tx", msgs.get(2)); } }
ReflectiveMethodInvocationTest
动态获取 AspectInstanceFactory
public class ReflectiveMethodInvocationTest extends AbstractV5Test{ private AspectJBeforeAdvice beforeAdvice = null; private AspectJAfterReturningAdvice afterReturningAdvice; private AspectJAfterThrowingAdvice afterThrowingAdvice; private NioCoderService nioCoderService; private AspectJExpressionPointcut pc = null; private BeanFactory beanFactory = null; private AspectInstanceFactory aspectInstanceFactory = null; @Before public void setUp() throws Exception { nioCoderService = new NioCoderService(); String expression = "execution(* com.niocoder.service.v5.*.placeOrder(..))"; pc = new AspectJExpressionPointcut(); pc.setExpression(expression); beanFactory = this.getBeanFactory("bean-v5.xml"); aspectInstanceFactory = this.getAspectInstanceFactory("tx"); aspectInstanceFactory.setBeanFactory(beanFactory); MessageTracker.clearMsgs(); beforeAdvice = new AspectJBeforeAdvice(TransactionManager.class.getMethod("start"), pc, aspectInstanceFactory); afterReturningAdvice = new AspectJAfterReturningAdvice(TransactionManager.class.getMethod("commit"), pc, aspectInstanceFactory); afterThrowingAdvice = new AspectJAfterThrowingAdvice(TransactionManager.class.getMethod("rollback"), pc, aspectInstanceFactory); } @Test public void textMethodInvocation() throws Throwable { Method targetMethod = NioCoderService.class.getMethod("placeOrder"); List<MethodInterceptor> interceptorList = new ArrayList<>(); interceptorList.add(beforeAdvice); interceptorList.add(afterReturningAdvice); ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, targetMethod, new Object[0], interceptorList); mi.proceed(); List<String> msgs = MessageTracker.getMsgs(); Assert.assertEquals(3, msgs.size()); Assert.assertEquals("start tx", msgs.get(0)); Assert.assertEquals("place order", msgs.get(1)); Assert.assertEquals("commit tx", msgs.get(2)); } @Test public void testAfterThrowing() throws Throwable{ Method targetMethod = NioCoderService.class.getMethod("placeOrderWithException"); List<MethodInterceptor> interceptorList = new ArrayList<>(); interceptorList.add(beforeAdvice); interceptorList.add(afterThrowingAdvice); ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, targetMethod, new Object[0], interceptorList); try { mi.proceed(); } catch (Throwable t) { List<String> msgs = MessageTracker.getMsgs(); Assert.assertEquals(2, msgs.size()); Assert.assertEquals("start tx", msgs.get(0)); Assert.assertEquals("rollback tx", msgs.get(1)); return; } Assert.fail("No Exception thrown"); } }
代码下载
解析aop:config标签
TODO ….
代码下载
参考资料
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
鸟哥的Linux私房菜 基础学习篇(第二版)
鸟哥 / 人民邮电出版社 / 2007-9 / 65.00元
《鸟哥的Linux私房菜基础学习篇(第二版)》全面而详细地介绍了Linux操作系统。全书分为5个部分:第一部分着重说明Linux的起源及功能,如何规划和安装Linux主机;第二部分介绍Linux的文件系统、文件、目录与磁盘的管理;第三部分介绍文字模式接口shell和管理系统的好帮手shell脚本,另外还介绍了文字编辑器vi和vim的使用方法;第四部分介绍了对于系统安全非常重要的Linux账号的管理......一起来看看 《鸟哥的Linux私房菜 基础学习篇(第二版)》 这本书的介绍吧!