**
1.简介
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。AspectJ 实现了aop的功能,且实现方式更为简捷,使用更为方便,而且还支持注解式开发。下面先介绍一下aop编程的一些术语。
2.aop的编程术语
切面(Aspect),织入(Weaving),连接点(JoinPoint),切入点(Pointcut),目标对象(Target),通知(Advice),顾问(Advisor)
3.AspectJ的通知
(1)前置通知
(2)后置通知
(3)环绕通知
(4)异常通知
(5)最终通知
4.AspectJ的切点表达式
AspectJ除了提供六种通知外,还定义了专门的表达式用于指定切入点。
execute([modifiers-pattern]访问权限类型
ret type-pattern 返回值类型
[declaring-type-pattern] 全限定性类名
name-pattern(param-pattern) 方法名
[throws-pattern] 抛出异常类型)
其中返回值类型和方法名不能省
注意:这里是两个点
符号 | 意义 |
---|---|
+ | 0至多个任意字符 |
. . | 用在方法参数中,表示任意多个参数,用在包名,表示当前包及其子包路径 |
* | 用在类名后,表示当前类及其子类,用在接口后,表示当前接口及其实现类 |
下面介绍一下常用的切点表达式
execution(* . .service.(. .))
指定所有包下service子包下所有类(接口)的所有方法为切入点
execution(* . .ISomeService.(. .))
指定所有包下ISomeService接口中的所有方法为切入点
5.Aop编程环境搭建
这是笔者用到的jar包,另外笔者用的是jdk1.8,下面是笔者的项目目录
废话少说,上代码
6.service类
package com.haichuang.services;
public interface ISomeService {
public void doSome();
public String doOther();
public void doThrid();
}
其实现类
package com.haichuang.services;
public class SomeServiceImpl implements ISomeService {
@Override
public void doSome() {
System.out.println("doSome");
}
@Override
public String doOther() {
System.out.println("doOther");
return "abc";
}
@Override
public void doThrid(){
System.out.println("doThrid"+3/0);
}
}
7.编AspectJ类
1)基于xml配置文件的实现
定义切面类
package com.haichuang.aopJ;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspectJClass {
//前置通知
public void before(){
System.out.println("MyAspectJ before");
}
//后置通知
public void afterReturning(Object result){
System.out.println("MyAspectJ afterReturning result="+result);
}
//环绕通知
public Object round(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("MyAspectJBefore round before");
Object obj=pjp.proceed();
if(obj!=null) {
//如果该方法有返回值就并且是String类型,就将他变成大写
obj=( (String)obj).toUpperCase();
}
System.out.println("MyAspectJBefore round after");
return obj;
}
//异常通知
public void afterThrowing(){
System.out.println("MyAspectJ afterThrowing");
}
//异常通知
public void afterThrowing(Exception ex){
System.out.println("MyAspectJ afterThrowing ex="+ex.getMessage());
}
//最终通知
public void after(){
System.out.println("MyAspectJ after");
}
}
xml文件配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="myAspect" class="com.haichuang.aopJ.MyAspectJClass"/>
<bean id="someService" class="com.haichuang.services.SomeServiceImpl"></bean>
<aop:config>
<aop:pointcut expression="execution(* *..ISomeService.doSome(..))" id="doSome"/>
<aop:pointcut expression="execution(* *..ISomeService.doOther(..))" id="doOther"/>
<aop:pointcut expression="execution(* *..ISomeService.doThrid(..))" id="doThird"/>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="doSome"/>
<aop:after-returning method="afterReturning(java.lang.Object)" returning="result" pointcut-ref="doOther"/>
<aop:around method="round" pointcut-ref="doOther"/>
<aop:after-throwing method="afterThrowing" throwing="ex" pointcut-ref="doThird"/>
<aop:after method="after" pointcut-ref="doThird"/>
</aop:aspect>
</aop:config>
</beans>
2)使用注解是开发
定义切面类
package com.haichuang.aopJ;
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 MyAspectJClass {
//前置通知
@Before("execution(* *..ISomeService.doSome(..))")
public void before(){
System.out.println("MyAspectJ before");
}
//后置通知
@AfterReturning(value="execution(* *..ISomeService.doOther(..))",returning="result")
public void afterReturning(Object result){
System.out.println("MyAspectJ afterReturning result="+result);
}
//环绕通知
@Around("execution(* *..ISomeService.doOther(..))")
public Object round(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("MyAspectJBefore round before");
Object obj=pjp.proceed();
if(obj!=null) {
//如果该方法有返回值就并且是String类型,就将他变成大写
obj=( (String)obj).toUpperCase();
}
System.out.println("MyAspectJBefore round after");
return obj;
}
//异常通知
@AfterThrowing("execution(* *..ISomeService.doThird(..))")
public void afterThrowing(){
System.out.println("MyAspectJ afterThrowing");
}
//异常通知
@AfterThrowing(value="doThird()",throwing="ex")
public void afterThrowing(Exception ex){
System.out.println("MyAspectJ afterThrowing ex="+ex.getMessage());
}
//最终通知
@After("doThird()")
public void after(){
System.out.println("MyAspectJ after");
}
// 定义了一个切入点,为doThird()
@Pointcut("execution(* *..ISomeService.doThrid(..))")
public void doThird() {}
}
xml配置文件就简单多了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="myAspect" class="com.haichuang.aopJ.MyAspectJClass"/>
<bean id="someService" class="com.haichuang.services.SomeServiceImpl"></bean>
<aop:aspectj-autoproxy/>
</beans>
8.测试类
package com.haichuang.demos;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import com.haichuang.services.ISomeService;
public class Demo {
public static void main(String[] args)
{
String resource="applicationContext.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
ISomeService isome=(ISomeService) ac.getBean("someService");
isome.doSome();
System.out.println("--------------");
System.out.println(isome.doOther());
System.out.println("--------------");
isome.doThrid();
}
}
下面是运行就结果
笔者在ISomeService的实现类SomeServiceImpl中加了3/0,所以有一个/ by zero异常