Spring(三、Spring AOP)

一、概念

AOP(Aspect Oriented Programming)概念:面向切面(方面)编程,扩展功能,不是通过修改源代码实现。

AOP采用横向抽取机制,取代了传统纵向集成体系重复性代码(性能监视、事务管理、安全检查、缓存)。
SpringAOP使用纯java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标植入增强代码。

AspectJ是一个基于java语言的AOP框架,Spring2.0开始,SpringAOP引入对Aspect的支持,AspectJ扩展了Java语言
,提供了一个专门的编译器,在编译时提供横向代码的植入。

二、原理

Spring的AOP的底层用到两种代理机制:

(1)JDK的动态代理:针对实现了接口的类产生代理。
(2)Cglib的动态代理:针对没有实现接口的类产生代理。应用的是底层的字节码增强技术,生成当前类的子类对象。

三、操作术语

Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.

Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.

Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置通知,后置
通知,异常通知,最终通知,环绕通知(切面要完成的功能)

Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类
动态地添加一些方法或 Field.

Target(目标对象):代理的目标对象

Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.
spring 采用动态代理织入,而AspectJ采用编译期织入和类装在期织入

Proxy(代理) :一个类被AOP 织入增强后,就产生一个结果代理类

Aspect(切面): 是切入点和通知(引介)的结合

四、基于Aspecj的xml准备工作

1、使用AspectJ需要导入SpringAOP 和 AspectJ相关jar包。
这里写图片描述

2、创建spriong核心配置文件,导入aop的约束。

<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.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>

3、使用表达式配置切入点

1.切入点:实际增强的方法
2.常用的表达式
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
(1)execution(* cn.itcast.aop.Book.add(..))  //对类中的ad地方法做增强。
(2)execution(* cn.itcast.aop.Book.*(..))//对类中的所有方法做增强。
(3)execution(* *.*(..)) //对所有类的所有方法做增强。
(4) 匹配所有save开头的方法 execution(* save*(..))// savaXXX方法

五、Aspectj的AOP操作

package com.chen.aop;
/**
 * 被增强类
 * @author chen
 *
 */
public class Book{  
    public void add() {
        System.out.println("book add....");
    }
}
package com.chen.aop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 增强类
 * @author chen
 *
 */
public class StrengthenBook {
    public void before1() {
        System.out.println("前置增强.....");
    }
}

配置文件配置:

<!-- 1、配置对象  -->
<bean id="book" class="com.chen.aop.Book"></bean>
<bean id="stengthenBook" class="com.chen.aop.StrengthenBook"></bean>

<!-- 2、配置aop操作 -->
<aop:config>
    <!-- 2.1配置切入点  切入点:指定对哪个方法进行增强。
        指定对book类的add()方法增强-->
    <aop:pointcut expression="execution(* com.chen.aop.Book.add(..))" id="pointcut1"/>
    <!-- 2.2配置切面 
        切面: 把增强用在具体方法的过程叫做切面-->
    <aop:aspect ref="stengthenBook">
        <!-- 配置增强的类型  method:增强类中的哪个方法作为增强。
            pointcut-ref:把增强用在哪个切入点上-->
        <aop:before method="before1" pointcut-ref="pointcut1"/>

    </aop:aspect>

</aop:config>

调用:

ApplicationContext context = new ClassPathXmlApplicationContext("aopbean.xml");
Book book = (Book) context.getBean("book");
book.add();

输出结果:
这里写图片描述

六、Aspectj的AOP其他操作

前置、后置、环绕通知:

增强类:

package com.chen.aop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 增强类
 * @author chen
 *
 */
public class StrengthenBook {
    public void before1() {
        System.out.println("前置增强.....");
    }

    public void after1() {
        System.out.println("后置增强....");
    }

    //环绕通知,在方法之前和之后都执行
    public void around1(ProceedingJoinPoint proceedingJoinPoint) {
        //方法之前执行
        System.out.println("环绕,方法之前执行.....");

        //执行被增强的方法
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //方法之后执行
        System.out.println("环绕,方法之后执行.....");
    }
}

配置文件:

    <!-- 1、配置对象  -->
    <bean id="book" class="com.chen.aop.Book"></bean>
    <bean id="stengthenBook" class="com.chen.aop.StrengthenBook"></bean>

    <!-- 2、配置aop操作 -->
    <aop:config>
        <!-- 2.1配置切入点  切入点:指定对哪个方法进行增强。
            指定对book类的add()方法增强-->
        <aop:pointcut expression="execution(* com.chen.aop.Book.add(..))" id="pointcut1"/>
        <!-- 2.2配置切面 
            切面: 把增强用在具体方法的过程叫做切面-->
        <aop:aspect ref="stengthenBook">
            <!-- 配置增强的类型  method:增强类中的哪个方法作为增强。
                pointcut-ref:把增强用在哪个切入点上-->
            <aop:before method="before1" pointcut-ref="pointcut1"/>
            <aop:after method="after1" pointcut-ref="pointcut1"/>
            <!-- 环绕通知 -->
            <aop:around method="around1" pointcut-ref="pointcut1"/>
        </aop:aspect>

    </aop:config>

调用:

public void testaop() {
    ApplicationContext context = new ClassPathXmlApplicationContext("aopbean.xml");
    Book book = (Book) context.getBean("book");
    book.add();
}

输出:
这里写图片描述

七、基于Aspectj的注解aop操作

@AspectJ提供的不同的通知类型。

通知类型:
* @Before :前置通知
* @AfterReturing :后置通知
* @Around :环绕通知
* @After :最终通知
* @AfterThrowing :异常抛出通知.

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: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.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--2、开启aop扫描操作  -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <!--1、创建对象 -->
    <bean id="book" class="com.chen.aop.annotation.Book"></bean>
    <bean id="stengthenBook" class="com.chen.aop.annotation.StrengthenBook"></bean>

</beans>

增强类:

package com.chen.aop.annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 增强类
 * @author chen
 *
 */
//在增强类上添加Aspect注解
@Aspect
public class StrengthenBook {

    //在方法上面,使用注解完成增强的配置
    @Before(value="execution(* com.chen.aop.annotation.Book.add(..))")
    public void before1() {
        System.out.println("annotation 前置增强.....");
    }

    @After(value="execution(* com.chen.aop.annotation.Book.add(..))")
    public void after1() {
        System.out.println("annotation 后置增强....");
    }

    //环绕通知,在方法之前和之后都执行
    @Around(value="execution(* com.chen.aop.annotation.Book.add(..))")
    public void around1(ProceedingJoinPoint proceedingJoinPoint) {
        //方法之前执行
        System.out.println("annotation 环绕,方法之前执行.....");

        //执行被增强的方法
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //方法之后执行
        System.out.println("annotation 环绕,方法之后执行.....");
    }
}

调用输出:

ApplicationContext context = new ClassPathXmlApplicationContext("aopannotationbean.xml");
Book book = (Book) context.getBean("book");
book.add();

输出结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值