AOP是Aspect-Oriented Programming的简称,中文就叫面向切面编程。
理论没什么好深究的,要理解Spring AOP,先看一个Spring AOP 的小Demo程序,有代码比较好理解。
先写一个简单的Service Demo:
import org.springframework.stereotype.Component;
@Component
public class TestService {
public void service() {
System.out.println("Test Service executing");
}
}
然后使用Spring容器加载启动:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.scan(Main.class.getPackage().getName());
annotationConfigApplicationContext.refresh();
TestService ts = annotationConfigApplicationContext.getBean(TestService.class);
ts.service();
}
}
控制台输出:
下面看看使用AOP对这个demo服务进行增强,首先需要使能Spring AOP:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class Config {
}
在@Configuration注解下跟上@EnableAspectJAutoProxy就可以使能AspectJ风格的AOP。
第二步定义pointcut,即切点:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class DemoPointCut {
@Pointcut("execution(* com.tubemogul.springsecuredemo.springDemo.aopbean.basicDemo.*.*(..))")
public void demoPointCut() {
}
}
切点就是描述这个Advice在什么地方”切入”,上面的代码就定义了个名字叫demoPointCut的切点(函数名就是切点名字),那么@Pointcut(“execution(* com.tubemogul.springsecuredemo.springDemo.aopbean.basicDemo..(..))”)就指示在什么地方切入了,这里表示在执行com.tubemogul.springsecuredemo.springDemo.aopbean.basicDemo包下任意类的任意方法都会被这个切入点切入。
定义完切点, 下面看Advice通知和Advisor通知器:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class DemoAdviceAdvisor {
@Around("com.tubemogul.springsecuredemo.springDemo.aopbean.basicDemo.DemoPointCut.demoPointCut()")
public Object demoAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("before service");
Object result = pjp.proceed();
System.out.println("after service");
return result;
}
}
这里的demoAround方法就是Advice通知,定义在连接点做什么,这是一个Around类型的通知。
而注解里的内容”com.tubemogul.springsecuredemo.springDemo.aopbean.basicDemo.DemoPointCut.demoPointCut()”就指示这个Advice通知使用前面定义的demoPointCut切点,这个就是通知器advisor,用于关联Advice和PointCut切点的。
这时候重新运行Main类,可以看到AOP已经顺利运行了:
Spring AOP和AspectJ的关系,SpringAOP 本身借助了org.aspectj.aspectjweaver包,aspectj是一套比Spring AOP更强大的AOP实现,但是aspectj的实现是基于编译时改变java class的行为实现AOP的,本身也可以算作一种新的编程语言。而Spring AOP的底层则是基于动态代理技术,在运行时生成动态代理类来实现AOP,但是Spring在顶层让用户定义AOP时借用了aspectj的接口和注解。这就是两者的关系。
当然Spring本身也可以集成aspectj,不过一般用不上。
Spring AOP官方文档:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-ataspectj,有更加详细的配置说明