预备知识:
Aspectj切入点语法定义
在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut”切入点”
切入点表达式 execution(* com.cwh.spring.aop.impl..(..))"
execution()是最常用的切点函数,其语法如下所示:
整个表达式可以分为五个部分:
1、execution(): 表达式主体。
2、第一个*号:表示返回类型, *号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.cwh.spring.aop.impl包、子孙包下所有类的方法。
4、第二个*号:表示类名,*号表示所有的类。
5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数
另外的:匹配com.cwh.spring.aop.implo包下所有类的所有方法; execution(* com.cwh.spring.aop.impl..*(..));
下面具体应用的例子: execution(* com.cwh.spring.aop.impl.ArithmeticCalculator.*(int, int))"表示ArithmeticCalculator类下的所有入参为(int, int)的方法
AOP正文:
jar包:
切面类:
package com.cwh.spring.aop.impl;
import java.util.Arrays;
import java.util.List;
import javax.naming.spi.DirStateFactory.Result;
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;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
*order注解,指定切面的优先级。值越小,优先级越高
*/
@Order(1)
[@Aspect](https://my.oschina.net/aspect)
[@Component](https://my.oschina.net/u/3907912)
public class LoginAspect {
// /**
// * 声明切入点表达式
// * @Pointcut(aspectj表达式)注解
// * 别的方法的注解的value引用pointcut注解的方法的方法名即可(此处例子为@After注解的value)
// */
// @Pointcut("execution(public int com.cwh.spring.aop.impl.ArithmeticCalculator.*(int, int))")
// public void declareJoinpointExprisseion(){}
// //execution执行
// //Aspect表达式:修饰符、返回类型、类、方法都能使用占位符"*"
// //public int com.cwh.spring.aop.impl.ArithmeticCalculator.*(int, int)
// @Before("execution(public int com.cwh.spring.aop.impl.ArithmeticCalculator.*(int, int))")
// public void beforMethod(JoinPoint joinPoint){
// //切入点的方法名
// String methodName = joinPoint.getSignature().getName();
// //切入点方法入参
// List<Object> list = Arrays.asList(joinPoint.getArgs());
// System.out.println("the method:"+methodName+" begin with:"+list);
// }
//
// //后置通知:不能返回目标方法结果。无论是否发生异常,都会执行的。
// @After("declareJoinpointExprisseion()")
// public void afterMethod(JoinPoint joinPoint){
// //切入点的方法名
// String methodName = joinPoint.getSignature().getName();
//切入点方法入参
List<Object> list = Arrays.asList(joinPoint.getArgs());
// System.out.println("the method:"+methodName+" end");
// }
//
// //可以访问到返回值result
// @AfterReturning(value = "execution(* com.cwh.spring.aop.impl.ArithmeticCalculator.*(..))",
// returning="result")
// public void afterReturnMethod(JoinPoint joinPoint, Object result){
// System.out.println("r方法:" + joinPoint.getSignature().getName() + " 结果:" + result);
// }
//
// //抛异常后执行的,可以访问到异常对象
// @AfterThrowing(value = "execution(* com.cwh.spring.aop.impl.ArithmeticCalculator.*(int, int))",
// throwing="exception")
// public void afterThrowing(JoinPoint joinPoint, Exception exception){
// System.out.println("t方法:" + joinPoint.getSignature().getName() + " 发生错误:" + exception);
// }
@Around(value="execution(* com.cwh.spring.aop.impl.ArithmeticCalculator.*(int, int))")
public Object around(ProceedingJoinPoint joinPoint){
Object result = null;
String methodName = joinPoint.getSignature().getName();
try {
//前置通知
System.out.println("方法前置通知:" + methodName + "参数:" + Arrays.asList(joinPoint.getArgs()));
//执行目标方法
result = joinPoint.proceed();
//后置通知
System.out.println("方法返回通知:" + result);
} catch (Throwable e) {
// e.printStackTrace();
//异常通知
System.out.println("the method "+ methodName +" occurs exception:"+e);
}
//后置通知
System.out.println("the method "+ methodName +" ends");
return result;
}
}
实现类:
package com.cwh.spring.aop.impl;
import org.springframework.stereotype.Component;
@Component(value = "arithmeticCalculatorImpl")
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
接口:
package com.cwh.spring.aop.impl;
public interface ArithmeticCalculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
测试类:
package com.cwh.spring.aop.impl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// 容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取bean实例
// 如果存在切面类,下面写法错误,bean工厂返回的是动态代理对象(不是实现类对象,是代理类的对象,getBean的入参决定了使用哪个实现类的实现方法)
// ArithmeticCalculatorImpl ari = (ArithmeticCalculatorImpl)
// context.getBean("arithmeticCalculatorImpl");
// 如果入参为classtype,子类不能有多个,否则发现不是唯一,不知道注入哪一个。如果是beanId则无妨
ArithmeticCalculator ari = (ArithmeticCalculator) context.getBean("arithmeticCalculatorImpl");
// 使用bean
int result = ari.add(5, 3);
// 当代理对象调用add方法时,实际上是代理对象委托bean id="arithmeticCalculatorImpl"对象调用
System.out.println("结果:" + result);
int result2 = ari.sub(15, 3);
// 当代理对象调用add方法时,实际上是代理对象委托bean id="arithmeticCalculatorImpl"对象调用
System.out.println("结果:" + result2);
}
}
applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<context:component-scan base-package="com.cwh.spring.aop.impl">
<!-- annotation:根据注解进行过滤,assignable:根据类进行过滤
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="assignable" expression="com.cwh.spring.bean.annotation.service.ApproveInterface"/>
-->
<!-- 如果使用include,需要去掉默认拦截器 use-default-filters="false"
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
</context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>