Spring笔记(3)AOP实现

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术语【掌握】

  1. target:目标类,需要被代理的类。例如:UserService
  2. Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
  3. PointCut 切入点:已经被增强的连接点。例如:addUser()
  4. advice 通知/增强,增强代码。例如:after、before
  5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
  6. proxy 代理类
  7. Aspect(切面): 是切入点pointcut和通知advice的结合
    1. ​ 一个线是一个特殊的面。
    2. ​ 一个切入点和一个通知,组成成一个特殊的面。
010.PNG

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 

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容