1.1 AOP介绍
1.1.1 什么是AOP
- AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
- 经典应用:事务管理、性能监视、安全检查、缓存 、日志等
- Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
- AspectJ是一个基于Java语言的AOP****框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
1.1.2 AOP实现原理
- aop底层将采用代理机制进行实现。
- 接口 + 实现类:spring采用 jdk 的动态代理Proxy。
- 实现类:spring 采用 cglib字节码增强。
1.1.3 AOP术语【掌握】
- target:目标类,需要被代理的类。例如:UserService
- Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
- PointCut 切入点:已经被增强的连接点。例如:addUser()
- advice 通知/增强,增强代码。例如:after、before
- Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
- proxy 代理类
- Aspect(切面): 是切入点pointcut和通知advice的结合
- 一个线是一个特殊的面。
- 一个切入点和一个通知,组成成一个特殊的面。
1.1.4手动方式
需要增强的类和方法
public class FirstController {
public void save( ){
//集合A中获取id 和 name
System.out.println(this.getClass()+" 调用.....save()");
}
}
增强的方法类
public class MyIntercepter {
public void getParameter(){
System.out.println("接收 request 中的参数 ,保存到 集合A");
}
public void checkModel(){
System.out.println("检测 Model 并保存到request 或 发送param ");
}
public void checkModelMap(){
System.out.println("检测 ModelMap 并保存到request 或 发送param ");
}
}
实现增强,继承需要增强的类,创建需要增强的方法类的实例
public class FirstControllerProxy extends FirstController{
MyIntercepter cpt = new MyIntercepter();
//织入
public void save(){
cpt.getParameter(); //bef
super.save();
cpt.checkModel(); //after
cpt.checkModelMap();//after
}
}
测试
public class Test {
public static void main(String[] args) {
//手动创建实例
FirstController fc = new FirstController();
fc.save();
System.out.println("-----------");
//spring 创建实例,我们只管调用
FirstController proxy = new FirstControllerProxy();
proxy.save();
}
}
结果如下
class com.senchen.ctrl.FirstController 调用.....save()
-----------
接收 request 中的参数 ,保存到 集合A
class com.senchen.proxy.FirstControllerProxy 调用.....save()
检测 Model 并保存到request 或 发送param
检测 ModelMap 并保存到request 或 发送param
1.1.5用spring xml配置方式
需要增强的类和方法
public class FirstController {
public void save( ){
//集合A中获取id 和 name
System.out.println(this.getClass()+" 调用.....save()");
}
public void list( ){
System.out.println(this.getClass()+"...list()");
}
}
增强的方法类
public class MyIntercepter {
public void getParameter(){
System.out.println("接收 request 中的参数 ,保存到 集合A");
}
public void checkModel(){
System.out.println("检测 Model 并保存到request 或 发送param ");
}
public void checkModelMap(){
System.out.println("检测 ModelMap 并保存到request 或 发送param ");
}
}
spring.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"
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.xsd">
<!-- aspect -->
<bean id="spct" class="com.senchen.asp.MyIntercepter"/>
<!-- controller -->
<bean id="fc" class="com.senchen.ctrl.FirstController"/>
<!-- 容器织入 -->
<aop:config>
<aop:pointcut id="ct" expression="execution(* com.senchen.ctrl.FirstController.*(..))"/>
<aop:aspect ref="spct">
<aop:before method="getParameter" pointcut-ref="ct"/>
<aop:after method="checkModel" pointcut-ref="ct"/>
<aop:after method="checkModelMap" pointcut-ref="ct"/>
</aop:aspect>
</aop:config>
</beans>
运行结果
接收 request 中的参数 ,保存到 集合A
class com.senchen.ctrl.FirstController 调用.....save()
检测 Model 并保存到request 或 发送param
检测 ModelMap 并保存到request 或 发送param
=====
接收 request 中的参数 ,保存到 集合A
class com.senchen.ctrl.FirstController...list()
检测 Model 并保存到request 或 发送param
检测 ModelMap 并保存到request 或 发送param
需要增强的类和方法
<!-- controller -->
<bean id="fc" class="com.senchen.ctrl.FirstController"/>
用来增强别的类的方法类
<!-- aspect -->
<bean id="spct" class="com.senchen.asp.MyIntercepter"/>
容器织入
要增强的类的方法
<aop:pointcut id="ct" expression="execution(* com.senchen.ctrl.FirstController.*(..))"/>
在id=ct指定的方法上增强id=spct的增强方法,在需要增强的方法前后加入增强方法
<aop:aspect ref="spct">
<aop:before method="getParameter" pointcut-ref="ct"/>
<aop:after method="checkModel" pointcut-ref="ct"/>
<aop:after method="checkModelMap" pointcut-ref="ct"/>
</aop:aspect>
1.1.5用spring注解方式
增强类的方法
@Component
@Aspect
public class MyIntercepter {
@Pointcut("execution( * com.senchen.ctrl.FirstController.*(..))")
public void f1(){}
@Before("f1()")
public void getParameter(){
System.out.println("接收 request 中的参数 ,保存到 集合A");
}
@After("f1()")
public void checkModel(){
System.out.println("检测 Model 并保存到request 或 发送param ");
}
public void checkModelMap(){
System.out.println("检测 ModelMap 并保存到request 或 发送param ");
}
}
@Component让spring.xml可以扫描到这个类
@Aspect相当于
<bean id="spct" class="com.senchen.asp.MyIntercepter"/>
标明这个类为来为别的类增强方法的类
@Pointcut("execution( * com.senchen.ctrl.FirstController.(..))")*相当于
<aop:pointcut id="ct" expression="execution(* com.senchen.ctrl.FirstController.*(..))"/>
该注解后的表达式指向需要增强的方法,在这些方法前或后增强,增强的方法为该注解下的方法
@Pointcut("execution( * com.senchen.ctrl.FirstController.*(..))")
public void f1(){}
@Before("f1()")
public void getParameter(){
System.out.println("接收 request 中的参数 ,保存到 集合A");
}
@After("f1()")
public void checkModel(){
System.out.println("检测 Model 并保存到request 或 发送param ");
}
@Before("") ,@After("")标注在让别的方法增强的方法上,括号里的参数为@Pointcut
注解下的方法名()表示在制定的方法前或后来执行@Before("") ,@After("")标注下的方法
需要增强的类和方法
@Component
public class FirstController {
public void save( ){
//集合A中获取id 和 name
System.out.println(this.getClass()+" 调用.....save()");
}
public void list( ){
System.out.println(this.getClass()+"...list()");
}
}
spring.xml配置,自动扫描包和自动识别aop的注解
<?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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.senchen"> <!-- 避免 spring-mvc 再次创建一个Controller 实例 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<aop:aspectj-autoproxy/>
</beans>
测试结果
接收 request 中的参数 ,保存到 集合A
class com.senchen.ctrl.FirstController 调用.....save()
检测 Model 并保存到request 或 发送param
=====
接收 request 中的参数 ,保存到 集合A
class com.senchen.ctrl.FirstController...list()
检测 Model 并保存到request 或 发送param