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 

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容