java aspectj apt_Spring 使用AspectJ的三种方式

Spring 使用AspectJ 的三种方式

一,使用JavaConfig

二,使用注解隐式配置

三,使用XML 配置

背景知识:

41f407cda58da8c912249ce459672578.png

110cfe1b1607f6811141ae16b1b6243a.png

注意 使用AspectJ 的 时候 要导入相应的Jar 包

7241af207680b93fed4f2e848b23253c.png

嗯 昨天还碰到了这样的问题:

Caused by: java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut ArithmeticPointCut

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 java.lang.IllegalStateException: Failed to load ApplicationContext2 at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)3 at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)4 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)5 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)6 at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)7 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)8 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)9 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)10 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)11 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)12 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)13 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)14 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)15 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)16 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)17 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)18 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)19 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)20 at org.junit.runners.ParentRunner.run(ParentRunner.java:363)21 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)22 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)23 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)24 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)25 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)26 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)27 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)28 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.event.internalEventListenerProcessor': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut ArithmeticPointCut

29 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)30 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)31 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)32 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)33 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)34 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)35 at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)36 at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)37 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)38 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)39 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)40 at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)41 at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)42 at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)43 at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)44 ... 25more45 Caused by: java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut ArithmeticPointCut

46 at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:317)47 at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:217)48 at org.springframework.aop.aspectj.AspectJExpressionPointcut.checkReadyToMatch(AspectJExpressionPointcut.java:190)49 at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:169)50 at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:220)51 at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:279)52 at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:311)53 at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:119)54 at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:89)55 at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:70)56 at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:346)57 at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298)58 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:423)59 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1633)60 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)61 ... 39 more

Error

更换了Jar 包  从 1.5 --> 换到了 1.8.10 就好了  注意  aspectj 和asectjweaver 要版本对应

JavaConfig

类的结构 如 下图 所示

d14504c2ec06d0b13bdf7cb54173aa4f.png

① Java Config

代码如下:  其中要注意@EnableAspectJAutoProxy(proxyTargetClass=true)   默认值为 false  只有开启proxyTargetClass 才会实现AspectJ 的切片功能

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.myth.spring.aop.config;2

3 importorg.springframework.context.annotation.ComponentScan;4 importorg.springframework.context.annotation.EnableAspectJAutoProxy;5 importorg.springframework.stereotype.Component;6

7 @Component8 @EnableAspectJAutoProxy(proxyTargetClass=true)9 @ComponentScan(basePackages="com.myth.spring.aop")10 public classArithmeticCaculatorConfig {11

12 }

ArithmeticCaculatorConfig

② Service 类下面就是最基本的 实现类 代码如下:

注意每个类前 要加上@Component的标签

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.myth.spring.aop.service;2

3 public interfaceIArithmeticCaculator {4 public int add(int a ,intb);5 public int sub(int a ,intb);6 public int mul(int a ,intb);7 public int div(int a ,intb);8 }

IArithmeticCaculator

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.myth.spring.aop.service.impl;2

3 importorg.springframework.stereotype.Component;4

5 importcom.myth.spring.aop.service.IArithmeticCaculator;6 importcom.myth.springAOP.exception.NotZeroException;7 @Component8 public class ArithmeticCaculatorImpl implementsIArithmeticCaculator{9

10 @Override11 public int add(int a, intb) {12 System.out.println(a +b);13 return a +b;14 }15

16 @Override17 public int sub(int a, intb) {18 return a -b;19 }20

21 @Override22 public int mul(int a, intb) {23 return a *b;24 }25

26 @Override27 public int div(int a, intb) {28 if (b == 0) {29 throw new NotZeroException("除数不能为空");30 }31 return a /b;32 }33 }

ArithmeticCaculatorImpl

③ Aspect 类

这个类中 需要注意的点就比较多了

我在其中只写了  @Before , @After 和 @AfterReturning

1.定义为@Aspect

2.定义@Pointcut  根据这个切点来描写方法

3.写其中的@Before 或者其他Aspect 方法

当我们调用JoinPoint 时  要 joinpoint  要选择org.aspectj.lang.JoinPoint

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.myth.spring.aop.service.aspect;2

3 importjava.util.Arrays;4

5 importorg.aspectj.lang.JoinPoint;6 importorg.aspectj.lang.annotation.AfterReturning;7 importorg.aspectj.lang.annotation.Aspect;8 importorg.aspectj.lang.annotation.Before;9 importorg.aspectj.lang.annotation.Pointcut;10 importorg.springframework.stereotype.Component;11

12 @Component13 @Aspect14 /**

15 * 要在Config中配置@EnableAspectJAutoProxy(proxyTargetClass=true) 默认为false16 * joinpoint 要选择org.aspectj.lang.JoinPoint17 *18 */

19 public classLoggingAspect {20 @Pointcut("execution(* com.myth.spring.aop.service.impl.ArithmeticCaculatorImpl.*(int , int ))")21 public voidArithmeticPointCut() {}22

23 @Before("ArithmeticPointCut()")24 public voidbefore(JoinPoint joinpoint) {25 String method =joinpoint.getSignature().getName();26 System.out.println("The method "+method+" begins with "+Arrays.asList(joinpoint.getArgs()));27 }28

29 /*@After(value= "ArithmeticPointCut()")30 public void After(JoinPoint joinpoint) {31 String method = joinpoint.getSignature().getName();32 System.out.println("The method "+method+" ends with ");33 }*/

34

35 @AfterReturning(value="ArithmeticPointCut()", returning = "result")36 public voidafterReturn(JoinPoint joinPoint ,Object result) {37 String method =joinPoint.getSignature().getName();38 System.out.println("The method "+method+" ends with " +result);39 }40 }

LoggingAspect

④ Junit 类

关于Junit 类 可以关注  我的这篇帖子

http://www.cnblogs.com/mythdoraemon/p/7533553.html

代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.myth.spring.aop.test;2

3 import static org.junit.Assert.*;4

5 importorg.junit.Test;6 importorg.junit.runner.RunWith;7 importorg.springframework.beans.factory.annotation.Autowired;8 importorg.springframework.test.context.ContextConfiguration;9 importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;10

11 importcom.myth.spring.aop.config.ArithmeticCaculatorConfig;12 importcom.myth.spring.aop.service.IArithmeticCaculator;13 @RunWith(SpringJUnit4ClassRunner.class)14 @ContextConfiguration(classes=ArithmeticCaculatorConfig.class)15 public classTestAspect {16

17 @Autowired18 privateIArithmeticCaculator iArithmeticCaculator;19

20 @Test21 public voidtest() {22 iArithmeticCaculator.add(1, 2);23 }24

25 }

TestAspect

注解注入

注解注入大部分与JavaConfig 很像 , 其实就是把Java Config 的内容去不都写到了XML 中 罢了

结构如下:

eb9d077844cbde53493157f712e4d3d0.png

我们跟上面的结构对应起来

① Java Config  这里应该是容器 applicationContext.xml

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4 xmlns:aop="http://www.springframework.org/schema/aop"

5 xmlns:context="http://www.springframework.org/schema/context"

6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd8 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

9

10

11

12

13

14

15

16

applicationContext.xml

② Service 类 与上面的代码一样  就不重复写了

③ Aspect 类 也与 前面的一样 这回我写的是Around 方法

Around 其实包括了其他4种切面方式

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 * 对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint . 它是 JoinPoint 的子接口, 允许控制何时执行,3 * 是否执行连接点.4 * 环绕通知必须有返回值,返回值为proceedingJoinPoint.proceed() 的结果5 *@paramproceedingJoinPoint6 */

7 @Around(value = "ArithmeticPointCut()")8 publicObject Around(ProceedingJoinPoint proceedingJoinPoint) {9 String method =proceedingJoinPoint.getSignature().getName();10 Object result = null;11 try{12 //相当于前置通知

13 System.out.println("The method " + method + " begins with " +Arrays.asList(proceedingJoinPoint.getArgs()));14 result =proceedingJoinPoint.proceed();15 //相当于后置返回通知

16 System.out.println("The method " + method + " ends with " +result);17 } catch(NotZeroException e) {18 //相当于异常通知

19 System.out.println("The method " + method + " occur an exception: " +e);20 throw new NotZeroException("除数不能为空");21 } catch(Throwable e) {22 //TODO Auto-generated catch block

23 e.printStackTrace();24 } finally{25 //相当于后置通知

26 System.out.println("The method " + method + " end");27 }28 returnresult;29 }

LoggingAspect#Around

④ Test 类

这回Test 类 跟上面的会有些不同

@ContextConfiguration(locations= {"classpath:applicationContext.xml"})

这样子加载ApplicationContext 资源

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.myth.spring.aop.annotion.test;2

3 importorg.junit.Test;4 importorg.junit.runner.RunWith;5 importorg.springframework.beans.factory.annotation.Autowired;6 importorg.springframework.test.context.ContextConfiguration;7 importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;8

9 importcom.myth.spring.aop.annotion.service.IArithmeticCaculator;10

11 @RunWith(SpringJUnit4ClassRunner.class)12 @ContextConfiguration(locations= {"classpath:applicationContext.xml"})13 public classTestAspect {14 @Autowired15 privateIArithmeticCaculator iArithmeticCaculator;16

17 @Test18 public voidtestAdd() {19 iArithmeticCaculator.add(1, 2);20 }21

22 @Test23 public voidtestDiv() {24 iArithmeticCaculator.div(1, 0);25 }26 }

TestAspect

XML配置

XML 配置其实就是把所有的切面方法写到applicationContext中

这里就只放上xml 配置文件

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4 xmlns:context="http://www.springframework.org/schema/context"

5 xmlns:aop="http://www.springframework.org/schema/aop"

6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd8 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

9

10

11

12

13

14

15

16

17

18

19

20 id="pointcut"/>

21

22

23

24

25

26

27

28

29

30

31

32

applicationContext.xml

总结:  我是建议用第一种方法

首先界面干净清晰 不用太依赖于xml文件

其次 因为我这个案例比较小, 如果切面有很多  其他的写法会有很多切面在XML 中存在  对了 我们可以设置Order 属性来确定切面的顺序, 在 XML 中 我有表现出这种形式

当然了  每种写法都可以, 大家择其喜欢的吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值