1.需要导入的jar包
spring-beans-
4.0
.0.
RELEASE
.
jar
spring
-context-
4.0
.0.RELEASE.
jar
spring
-core-
4.0
.0.RELEASE.
jar
spring
-expression-
4.0
.0.
RELEASE
.
jar
commons-logging-
1.1
.3.
jar
spring
-aop-
4.0
.0.
RELEASE
.
jar
//以下是AOP需要额外导入的jar包
spring
-aspects-
4.0
.0.RELEASE.
jar
2.AOP中的注解
- @Aspect
- 声明某一个类是一个切面类
- 声明为切面类的同时还需要交给IOC容器管理
@Aspect
// 声明当前类是一个切面类
@Component
// 将当前类交给IOC容器管理
public
class
LoggingAspect {
- @Pointcut
- 声明切入点表达式
//声明切入点表达式
@Pointcut
(
"execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))"
)
public
void
pointCut(){};
- @Before
- 声明前置通知
- 前置通知在方法执行之前调用
// 前置通知,在目标方法调用之前执行
@Before
(value =
"pointCut()"
)
public
void
beforeAdvice(JoinPoint
jp
) {
// 获取方法名
String
name
=
jp
.getSignature().getName();
// 获取参数
Object[]
args
=
jp
.getArgs();
System.
out
.println(
"[★★★Logging]The method "
+
name
+
" begins with "
+ Arrays.
asList
(
args
));
}
- @After
- 声明后置通知
- 后置通知在方法执行完成后调用(不管是否发生异常)
// 后置通知,在目标方法执行完成之后执行(不管是否发生异常)
@After
(
"pointCut()"
)
public
void
afterAdvice(JoinPoint
jp
) {
// 获取方法名
String
name
=
jp
.getSignature().getName();
System.
out
.println(
"[★★★Logging]The method "
+
name
+
" ends"
);
}
- @AfterReturning
- 声明返回通知
- 返回通知在方法执行完之后调用
//返回通知,在目标方法执行后执行
@AfterReturning
(pointcut =
"execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))"
,returning=
"result"
)
public
void
returnAdvice(JoinPoint
jp
, Object
result
) {
// 获取方法名
String
name
=
jp
.getSignature().getName();
System.
out
.println(
"[★★★Logging]The method "
+
name
+
" returns "
+
result
);
}
- @AfterThrowing
- 声明异常通知
- 异常通知在方法执行出现异常时调用
//异常通知,在目标方法执行出现异常时执行
@AfterThrowing
(pointcut =
"execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))"
,throwing=
"e"
)
public
void
returnAdvice(JoinPoint
jp
, Exception
e
) {
// 获取方法名
String
name
=
jp
.getSignature().getName();
System.
out
.println(
"[★★★Logging]The method "
+
name
+
" occours "
+
e
);
}
- @Around(使用环绕通知必须将前面的前后等方法注掉)
- 声明环绕通知
- 环绕通知相当于动态代理的全过程
//环绕通知,相当于动态代理的全过程
@Around
(
"pointCut()"
)
public
Object roundAdvice(ProceedingJoinPoint
pjp
) {
//获取方法名
String
name
=
pjp
.getSignature().getName();
//获取参数
Object[]
args
=
pjp
.getArgs();
Object
result
=
null
;
try
{
//前置通知
System.
out
.println(
"[★★★★★Logging]The method "
+
name
+
" begins with "
+ Arrays.
asList
(
args
));
//执行目标方法
result
=
pjp
.proceed();
//返回通知
System.
out
.println(
"[★★★★★Logging]The method "
+
name
+
" returns "
+
result
);
}
catch
(Throwable
e
) {
//异常通知
System.
out
.println(
"[★★★★★Logging]The method "
+
name
+
" occours "
+
e
);
// e.printStackTrace();
}
finally
{
//后置通知
System.
out
.println(
"[★★★★★Logging]The method "
+
name
+
" ends"
);
}
return
result
;
}
- @Order
- 声明切面的优先级
- 通过该注解中的value属性值来设置切面的优先级,里面传入一个int类型的值,值越小优先级越高,默认值是Integer的最大值
@Order
(10)
//可以通过@Order注解中的value属性设置切面的优先级,value属性值越小优先级越高,默认值是Integer的最大值
@Aspect
// 声明当前类是一个切面类
@Component
// 将当前类交给IOC容器管理
public
class
ValidateAspect {
- Spring的配置文件中的配置
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
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.atguigu.spring.aop"
></
context:component-scan
>
<!-- 启用 AspectJ 注解支持:Spring会自动创建代理对象 -->
<
aop:aspectj-autoproxy
></
aop:aspectj-autoproxy
>
</
beans
>
package com.atguigu.spring.aop;
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;
import org.springframework.stereotype.Component;
@Aspect // 声明当前类是一个切面类
@Component // 将当前类交给IOC容器管理
public class LoggingAspect {
//声明切入点表达式
@Pointcut("execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))")
public void pointCut(){};
/**
* 切入点表达式的表示方式: ①execution(public int
* com.atguigu.spring.aop.ArithmeticCalculator.add(int, int))
* execution(public int ArithmeticCalculator.add(int, int))
* -只有调用ArithmeticCalculator接口中的add()方法时才会执行对应的通知 -如果切面类与接口和实现类在同一个包下,包名可以省略
* ②execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int,
* int)) --只有调用ArithmeticCalculator接口中的所有的方法时都会会执行对应的通知 ③execution(*
* com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))
* --调用ArithmeticCalculator接口中的所有的方法时都会会执行对应的通知,而且不考虑权限修饰符和返回值类型
* ④execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))
* --调用ArithmeticCalculator接口中的所有的方法时都会会执行对应的通知,而且不考虑权限修饰符和返回值类型以及参数的类型和个数
* ⑤execution(* *.*(..)) --调用所有接口的方法时都会会执行对应的通知,而且不考虑权限修饰符和返回值类型以及参数的类型和个数
*
*/
// 前置通知,在目标方法调用之前执行
@Before(value = "pointCut()")
public void beforeAdvice(JoinPoint jp) {
// 获取方法名
String name = jp.getSignature().getName();
// 获取参数
Object[] args = jp.getArgs();
System.out.println("[★★★Logging]The method " + name + " begins with " + Arrays.asList(args));
}
// 后置通知,在目标方法执行完成之后执行(不管是否发生异常)
@After("pointCut()")
public void afterAdvice(JoinPoint jp) {
// 获取方法名
String name = jp.getSignature().getName();
System.out.println("[★★★Logging]The method " + name + " ends");
}
//返回通知,在目标方法执行后执行
@AfterReturning(pointcut = "execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))",returning="result")
public void returnAdvice(JoinPoint jp , Object result) {
// 获取方法名
String name = jp.getSignature().getName();
System.out.println("[★★★Logging]The method " + name + " returns "+result);
}
//异常通知,在目标方法执行出现异常时执行
@AfterThrowing(pointcut = "execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))",throwing="e")
public void returnAdvice(JoinPoint jp , Exception e) {
// 获取方法名
String name = jp.getSignature().getName();
System.out.println("[★★★Logging]The method " + name + " occours "+e);
}
//环绕通知,相当于动态代理的全过程
@Around("pointCut()")
public Object roundAdvice(ProceedingJoinPoint pjp) {
//获取方法名
String name = pjp.getSignature().getName();
//获取参数
Object[] args = pjp.getArgs();
Object result = null;
try {
//前置通知
System.out.println("[★★★★★Logging]The method " + name + " begins with " + Arrays.asList(args));
//执行目标方法
result = pjp.proceed();
//返回通知
System.out.println("[★★★★★Logging]The method " + name + " returns "+result);
} catch (Throwable e) {
//异常通知
System.out.println("[★★★★★Logging]The method " + name + " occours "+e);
// e.printStackTrace();
} finally{
//后置通知
System.out.println("[★★★★★Logging]The method " + name + " ends");
}
return result;
}
}
test
package com.atguigu.spring.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.atguigu.spring.aop.ArithmeticCalculator;
public class AopTest {
// 创建IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans-aop.xml");
@Test
public void testAOP() {
ArithmeticCalculator atc = (ArithmeticCalculator) ioc.getBean("arithmeticCalculator");
// 进行加、减、乘、除的运算
int add = atc.add(10, 2);
System.out.println(add);
int sub = atc.sub(10, 2);
System.out.println(sub);
int mul = atc.mul(10, 2);
System.out.println(mul);
int div = atc.div(10, 0);
System.out.println(div);
}
}
3.基于XML的形式配置AOP
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
xsi:schemaLocation
=
"
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"
;
>
<!-- 配置数学计算器的实现类bean -->
<
bean
id
=
"arithmeticCalculator"
class
=
"com.atguigu.spring.xml.ArithmeticCalculatorImpl"
></
bean
>
<!-- 配置切面类bean -->
<
bean
id
=
"loggingAspect"
class
=
"com.atguigu.spring.xml.LoggingAspect"
></
bean
>
<!-- 配置AOP -->
<
aop:config
>
<!-- 配置切入点表达式 -->
<
aop:pointcut
expression
=
"execution(* com.atguigu.spring.xml.ArithmeticCalculator.*(..))"
id
=
"pointCut"
/>
<!-- 配置切面 -->
<
aop:aspect
ref
=
"loggingAspect"
>
<!-- 前置通知 -->
<
aop:before
method
=
"beforeAdvice"
pointcut-ref
=
"pointCut"
/>
<!-- 后置通知 -->
<
aop:after
method
=
"afterAdvice"
pointcut-ref
=
"pointCut"
/>
<!-- 返回通知 -->
<
aop:after-returning
method
=
"returnAdvice"
pointcut-ref
=
"pointCut"
returning
=
"result"
/>
<!-- 异常通知 -->
<
aop:after-throwing
method
=
"exceptionAdvice"
pointcut-ref
=
"pointCut"
throwing
=
"e"
/>
<!-- 环绕通知 -->
<
aop:around
method
=
"roundAdvice"
pointcut-ref
=
"pointCut"
/>
</
aop:aspect
>
</
aop:config
>
</
beans
>
package com.atguigu.spring.xml;
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;
import org.springframework.stereotype.Component;
public class LoggingAspect {
// 前置通知,在目标方法调用之前执行
public void beforeAdvice(JoinPoint jp) {
// 获取方法名
String name = jp.getSignature().getName();
// 获取参数
Object[] args = jp.getArgs();
System.out.println("[▲Logging]The method " + name + " begins with " + Arrays.asList(args));
}
// 后置通知,在目标方法执行完成之后执行(不管是否发生异常)
public void afterAdvice(JoinPoint jp) {
// 获取方法名
String name = jp.getSignature().getName();
System.out.println("[▲Logging]The method " + name + " ends");
}
//返回通知,在目标方法执行后执行
public void returnAdvice(JoinPoint jp , Object result) {
// 获取方法名
String name = jp.getSignature().getName();
System.out.println("[▲Logging]The method " + name + " returns "+result);
}
//异常通知,在目标方法执行出现异常时执行
public void exceptionAdvice(JoinPoint jp , Exception e) {
// 获取方法名
String name = jp.getSignature().getName();
System.out.println("[▲Logging]The method " + name + " occours "+e);
}
//环绕通知,相当于动态代理的全过程
public Object roundAdvice(ProceedingJoinPoint pjp) {
//获取方法名
String name = pjp.getSignature().getName();
//获取参数
Object[] args = pjp.getArgs();
Object result = null;
try {
//前置通知
System.out.println("[▲▲Logging]The method " + name + " begins with " + Arrays.asList(args));
//执行目标方法
result = pjp.proceed();
//返回通知
System.out.println("[▲▲Logging]The method " + name + " returns "+result);
} catch (Throwable e) {
//异常通知
System.out.println("[▲▲Logging]The method " + name + " occours "+e);
// e.printStackTrace();
} finally{
//后置通知
System.out.println("[▲▲Logging]The method " + name + " ends");
}
return result;
}
}
test
package com.atguigu.spring.test;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.atguigu.spring.xml.ArithmeticCalculator;
public class Aop_xmlTest {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans-xml.xml");
@Test
public void testAOP_xml() {
ArithmeticCalculator atc = (ArithmeticCalculator) ioc.getBean("arithmeticCalculator");
// 进行加、减、乘、除的运算
int add = atc.add(10, 2);
System.out.println(add);
int sub = atc.sub(10, 2);
System.out.println(sub);
int mul = atc.mul(10, 2);
System.out.println(mul);
int div = atc.div(10, 2);
System.out.println(div);
}
}