在使用的時候,遇到了部分的異常,我用的是最新的Spring版本,Spring-4.2.5版本的,首先確保你的配置文件中引入了下面紅色部分。
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
1. aspectjrt.jar
2.aspectjweaver.jar
3.aopalliance-1.0.jar
我在使用的時候由於沒有使用第三個jar包導致了異常信息如下:
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1105) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1050) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:228) at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:687) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:523) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext. (ClassPathXmlApplicationContext.java:83) at com.siti.spring20160315aop.MainTest.main(MainTest.java:9) Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098) ... 13 more
下面開始使用AspectJ進行切面配置
定義四個接口,下面讓WangYang類實現這個Person的接口,並實現其中的方法。
package com.siti.spring20160315aop; public interface Person { void say(); void sayName(String name); String saySth(String name); void sayEx(); }
其中saySth這個方法設置了返回值,這個地方會被AfterReturning織入,然後sayEx方法為了測試故意利用空指針異常,測試AfterThrowing會不會被織入。
package com.siti.spring20160315aop; public class WangYang implements Person{ @Override public void say() { System.out.println("wy!"); } @Override public void sayName(String name) { System.out.println("name-->" + name); } @Override public String saySth(String name) { System.out.println("name-->" + name); return name; } @Override public void sayEx() { Object obj = null; obj.equals("1"); } }
面向切面編程AspectJ的實現,主要方式如下,其中,after通知主要用於釋放資源,afterReturning通知可以對返回值進行更改,afterThrowing通知可以進行異常捕獲生成異常記錄,before這個通知可以進行參數的校驗之類的。
package com.siti.spring20160315aop; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyInterceptor { @Pointcut("execution(* com.siti.spring20160315aop.WangYang.*(..))") public void anyMethod(){} @Before("anyMethod()") public void checkMessage(JoinPoint joinPoint){ System.out.println("@Before-check!!!"); System.out.println("@Before-目標對象為:" + joinPoint.getTarget()); System.out.println("@Before-目標方法:" + joinPoint.getSignature().getName()); System.out.println("@Before-目標方法的參數:" + Arrays.toString(joinPoint.getArgs())); } @AfterReturning(pointcut = "anyMethod()", returning = "obj") public void checkReturn(JoinPoint joinPoint, Object obj){ System.out.println("@AfterReturning-目標方法返回值:" + obj); System.out.println("@AfterReturning-生成日志"); System.out.println("@AfterReturning-目標對象為:" + joinPoint.getTarget()); System.out.println("@AfterReturning-目標方法:" + joinPoint.getSignature().getName()); System.out.println("@AfterReturning-目標方法的參數:" + Arrays.toString(joinPoint.getArgs())); } @After("anyMethod()") public void checkAfter(JoinPoint joinPoint){ System.out.println("@After-釋放資源!"); System.out.println("@After-目標對象為:" + joinPoint.getTarget()); System.out.println("@After-目標方法:" + joinPoint.getSignature().getName()); System.out.println("@After-目標方法的參數:" + Arrays.toString(joinPoint.getArgs())); } @Around("anyMethod()") public Object checkAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("@Around!"); Object[] args = joinPoint.getArgs(); if(args != null && args.length > 0 && args[0].getClass() == String.class){ args[0] = "@Around" + args[0]; } Object result = joinPoint.proceed(args); if(result != null && result.getClass() == String.class){ result = result + "--wy"; } return result; } @AfterThrowing(throwing = "ex", pointcut = "anyMethod()") public void checkAfterThrowing(Throwable ex){ System.out.println("@AfterThrowing-異常拋出!"); System.out.println("@AfterThrowing-異常日志!"); } }
配置文件需要將我們自己寫的這個切面的類,在配置文件中進行“注冊”。
測試:
package com.siti.spring20160315aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext20160315.xml"); Person wy = context.getBean("wy", Person.class); wy.say(); wy.sayName("wangyang-"); String str = wy.saySth("hello--"); System.out.println("str的值:" + str); // wy.sayEx();// 拋出異常的測試 } }
基於配置文件配置的方式和前面的注解的方式基本上類似的,這裡只是將,改動的地方列出來,不做介紹了。
配置文件如下:
package com.siti.spring20160315aopwithxml; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class MyInterceptor { public void anyMethod(){} public void checkMessage(JoinPoint joinPoint){ System.out.println("@Before-check!!!"); System.out.println("@Before-目標對象為:" + joinPoint.getTarget()); System.out.println("@Before-目標方法:" + joinPoint.getSignature().getName()); System.out.println("@Before-目標方法的參數:" + Arrays.toString(joinPoint.getArgs())); } public void checkReturn(JoinPoint joinPoint, Object obj){ System.out.println("@AfterReturning-目標方法返回值:" + obj); System.out.println("@AfterReturning-生成日志"); System.out.println("@AfterReturning-目標對象為:" + joinPoint.getTarget()); System.out.println("@AfterReturning-目標方法:" + joinPoint.getSignature().getName()); System.out.println("@AfterReturning-目標方法的參數:" + Arrays.toString(joinPoint.getArgs())); } public void checkAfter(JoinPoint joinPoint){ System.out.println("@After-釋放資源!"); System.out.println("@After-目標對象為:" + joinPoint.getTarget()); System.out.println("@After-目標方法:" + joinPoint.getSignature().getName()); System.out.println("@After-目標方法的參數:" + Arrays.toString(joinPoint.getArgs())); } public Object checkAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("@Around!"); Object[] args = joinPoint.getArgs(); if(args != null && args.length > 0 && args[0].getClass() == String.class){ args[0] = "@Around" + args[0]; } Object result = joinPoint.proceed(args); if(result != null && result.getClass() == String.class){ result = result + "--wy"; } return result; } public void checkAfterThrowing(Throwable ex){ System.out.println("@AfterThrowing-異常拋出!"); System.out.println("@AfterThrowing-異常日志!"); } }