需要引入的依赖,maven配置:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
spring-config配置:
<span style="color:#330033;"><?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: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-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="com.along.apple" use-default-filters="true">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 通过aop命名空间的<aop:aspectj-autoproxy/>声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面-->
</span><span style="color:#ff0000;"> <aop:aspectj-autoproxy /></span><span style="color:#330033;">
<bean id="apple" class="com.along.apple.aop.Apple"/>
</beans></span>
特别需要注意,注解方式实现的AOP在配置文件中一定要添加<aop:aspectj-autoproxy />否则注解不起作用,切面无法织入目标对象,原因是该配置标示等同于引入AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,并完成创建代理织入切面的工作。
AOP注入的目标类:
@Service
public class Apple {
/**
*
* @param appleName
*/
public void addApple(String appleName){
System.out.println("加入一个苹果:"+appleName);
}
/**
*
* @param appleName
*/
public void deleteApple(String appleName){
System.out.println("删除一个苹果"+appleName);
}
/**
*
* @param appleName
*/
public void editAppple(String appleName){
System.out.println("修改一个苹果的属性"+appleName);
}
}
简单AOP切面实现:
@Component
@Aspect
public class SimpleAspect {
public static final String ASPECT_SERVICE_EXCUTION = "execution(* com.along.apple.aop..*.*(..))";
/**
* 切点表达式,方便书写,不实现任何内容
* 也可没有该方法,直接写切点
*/
@Pointcut(ASPECT_SERVICE_EXCUTION)
public void MyPointCut() {
}
@After("MyPointCut()")
public void after(JoinPoint joinPoint) {
System.out.println("后置通知after aspect executed.........");
}
@Before("MyPointCut()")
public void before(JoinPoint joinPoint) {
//如果需要这里可以取出参数进行处理
Object[] args = joinPoint.getArgs();
System.out.println("连接点信息" + joinPoint.getThis()
+ "目标对象"+ joinPoint.getTarget()
+ "当前连接点签名"+ joinPoint.getSignature()
+ "连接点方法所在类文件中的位置" + joinPoint.getSourceLocation());
System.out.println("前置通知before aspect executing");
}
@AfterReturning(pointcut = "MyPointCut()", returning = "returnVal")
public void afterReturning(JoinPoint joinPoint, Object returnVal) {
System.out.println("返回后通知afterReturning executed, return result is "
+ returnVal);
}
@Around("MyPointCut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前处理通知around start..");
try {
pjp.proceed();
} catch (Throwable ex) {
System.out.println("error in around");
throw ex;
}
System.out.println("环绕后处理通知around end");
}
@AfterThrowing(pointcut = "MyPointCut()", throwing = "error")
public void afterThrowing(JoinPoint jp, Throwable error) {
System.out.println("异常通知error:" + error);
}
}
入口类:
public class AopTest {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config*.xml");
Apple apple =(Apple)context.getBean("apple");
apple.addApple("红苹果");
}
}
运行结果如下图,可以比较几种通知的通知顺序:
环绕前处理通知around start..
连接点信息....
前置通知before aspect executing
加入一个苹果:红苹果
环绕后处理通知around end
后置通知after aspect executed.........
返回后通知afterReturning executed, return result is null