Spring AOP-- XML配置

Spring AOP

代理目标 (Target) : 谁将被其他对象代理,谁就是代理目标
代理对象(proxy) : 谁将代理其他对象,谁就是代理对象
连接点( Join Point ) : 连接点 = 执行点 + 方位
  1. 执行点:任意一个可以执行的方法都可以当作一个执行点
  2. 方位
  • 方法执行前 ( Before ):在方法调用之前调用通知
  • 方法正常返回后 (After-returning):在方法执行成功之后调用通知
  • 方法抛出异常后 (After-throwing):在方法抛出异常后进行通知
  • 方法执行后 (after):在方法完成之后调用通知,无论方法执行成功与否
  • 方法执行前和后 (Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
切点 ( Pointcut ) : (确定在哪里加入代码)
  • 对连接点进行筛选的条件
  • 要指定执行点和方位信息
  • 确定在哪里加入代码
Advice:(确定加入什么代码)
  • 在指定的切点 所选择的连接点加入的代码
切面(Aspect):切面(Aspect)= 切点(Pointcut)+ Advice
  • 在哪里加?加什么代码?
织入( Weaver ):
  • Advice对应的代码 加入到切点所选择的连接点的过程
  • 实现方式:
    <1> 编译时织入
    <2> 类加载时织入
    <3> 运行期织入
引入 ( Introduction ):

Spring AOP 的实现过程

工程一

【1、在parent (父模块) 模块添加依赖】
<!--声明版本-->
<aspectj.version>1.9.2</aspectj.version> <!-- ${aspectj.version} -->

<!--添加依赖-->
      <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>${aspectj.version}</version>
      </dependency>

      <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>${aspectj.version}</version>
      </dependency>

Spring AOP 的内部实现需要依赖于 AspectJ

AspectJ 是基于 JVM 的 支持 AOP 操作的一种语言。

【2、新建 aop 模块 】

pom.xm:

      <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
      </dependency>

      <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
      </dependency>
  • man/java 目录下创建 com.itlaobing.aop.schema 包

  • man/resources/ 目录下创建 com/itlaobing/aop/schema

  • test/java/ 目录下创建 com/itlaobing/aop/schema

【3、创建 Swimmable 、Tortoise 、SwimAdvices 】

Swimmable :

package com.itlaobing.aop.schema;

public interface Swimmable {
    void swim();
}

Tortoise :

package com.itlaobing.aop.schema;

public class Tortoise implements Swimmable {
    @Override
    public void swim() {
        System.out.println("乌龟在游泳");
    }

    @Override
    public String toString() {
        System.out.println( "[ " + this.getClass().getCanonicalName() + " : toString() ]");
        return "Tortoise[ " + Integer.toHexString( System.identityHashCode( this ) )+ " ]";
    }
}

SwimAdvices :

package com.itlaobing.aop.schema;

public class SwimAdvices {

    public void abc(){

        System.out.println("即将执行");
    }

    public void xyz(){
        System.out.println("即将结束");
    }
}

【4、创建 Spring 配置文件 】
<?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">
    <!-- 确定需要 添加的代码所在的 bean -->
    <bean id="abvices" class="com.itlaobing.aop.schema.SwimAdvices"/>

    <!-- 确定代理目标(谁将被代理) -->
    <bean id="tortoise" class="com.itlaobing.aop.schema.Tortoise"/>
    
    <!-- 提供 AOP 配置  -->
    <aop:config>

        <aop:aspect ref="abvices">
            <!-- 通过 aop:pointcut 来声明一个【切点】 ( 这个切点在 aop:aspect 内部,所以是局部切点 ) -->
            <!-- 通过 aop:pointcut 标签的 expression  来指定切点表达式 -->
            <aop:pointcut id="firstPointcut" expression="execution(* com.itlaobing.aop.schema.Tortoise.*() )"/>
            <!-- 在  firstPointcut 所选择 【连接点】( 指定的 执行点 执行之前 ) 处 加入 advices 中的 before 方法 对应的代码 -->
            <!-- 在 firstPointcut 所选择的那些方法之前前 先执行  advices 对象 before 方法-->
            <aop:before pointcut-ref="firstPointcut" method="abc"/>
            <aop:after pointcut-ref="firstPointcut" method="xyz"/>
        </aop:aspect>
</beans>
【5、测试 】
package com.itlaobing.aop.schema;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestTortoise {
    public static void main( String[] args ) {

        //指定configguration metadata
        String configLocations ="classpath:com/itlaobing/aop/schema/aop-schema.xml";

        // 创建 Spring IoC 容器
        AbstractApplicationContext container = new ClassPathXmlApplicationContext(configLocations);

        // 从容器中获取 指定 id 对应的 bean , 并明确其类型
        Object proxy = container.getBean("tortoise");

        System.out.println(proxy.getClass());
        System.out.println(proxy.toString());

        if (proxy instanceof Swimmable){

            Swimmable s =(Swimmable)proxy;
            s.swim();
        }
        container.close();
    }
}

工程二

【1、创建 Cat、CatAdvices、】

Cat:

package com.itlaobing.aop.schema;
public class Cat {
	private String name;
	
	public void eat(String food){
       System.out.println( this.name + "吃" + food 
       }

       public int div(int a , int b ){
        int c = a / b ;
        return c ;
    }

    public String getName(){
        return name;
    }

    public void setName( String name){
        this.name=name;
    }
}

CatAdvices:

package com.itlaobing.aop.schema;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;

import java.lang.reflect.Modifier;
import java.util.Arrays;

public class CatAdvices {
    /**
     * 任意的一个 Advice 对应的方法中,第一个参数都可以是  org.aspectj.lang.JoinPoint <br>
     * 通过 JoinPoint 可以在 Advice 对应的方法内部 访问 连接点 的信息 ( 就是可以访问 被拦截的方法的信息 )
     */
    public void before( JoinPoint joinPoint ) {
        // 获取 连接点 对应的 方法 的 签名
        Signature signature = joinPoint.getSignature();
        System.out.println("signature : " + signature);
        // 获得方法的 修饰符 ( 以整数形式返回 )
        int mod = signature.getModifiers();
        //将 整数形式表示的 修饰符 解析为 字符串 形式
        String modifiers = Modifier.toString(mod);
        System.out.println("modifiers: " + modifiers);
        // 获取 方法名称
        String methodName = signature.getName();
        System.out.println("name : " + methodName);
        // 获取被拦截的方法在执行时接受的 实参
        Object[] args = joinPoint.getArgs();
        System.out.println("arguments : " + Arrays.toString(args));

        System.out.println("【 " + methodName + " 】方法即将执行");
     }
        /**
         * 环绕( around )
         * @param joinPoint 必须是 ProceedingJoinPoint 类型
         * @return
         * @throws Throwable
         */
        public Object around ( ProceedingJoinPoint joinPoint) throws Throwable {
            String  name = joinPoint.getSignature().getName();
            System.out.println( "开始为" + name + "计时" );
            long begin = System.nanoTime();

            Object result = joinPoint.proceed() ; // 通过 ProceedingJoinPoint 的  proceed 方法让被拦截的方法继续执行

            long end = System.nanoTime();
            System.out.println( "为" + name + "计时结束" );
            System.out.println( "[ " + name + " ]执行耗时 [ " + ( end - begin ) + "ns, ]" );

            // 返回 由  被拦截的方法执行后 所返回的值
            return result ;
        }

        public void afterReturn(JoinPoint joinPoint , Object returnValue ){
            System.out.println("【" + joinPoint.getSignature().getName() + " 】方法执行后返回了【 " + returnValue +" 】" );
        }

        public  void afterThrow (JoinPoint joinPoint , Throwable ex) {
            System.out.println("【" + joinPoint.getSignature().getName() + " 】方法执行时抛出了【 " + ex + " 】" );
        }
    public void after( JoinPoint joinPoint ) {
        Signature signature = joinPoint.getSignature();
        String methodName = signature.getName() ;
        System.out.println( "【 " + methodName + " 】方法执行结束" );
    }
}

【2、创建 Spring 配置文件】
<?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:p="http://www.springframework.org/schema/p"
       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">
    <!-- 确定需要 添加的代码所在的 bean -->
     <bean id="CatAdvices" class="com.itlaobing.aop.schema.CatAdvices"/>


  <!-- 确定代理目标(谁将被代理) -->
     <bean id="Cat" class="com.itlaobing.aop.schema.Cat" p:name="汤姆"/>
<!-- 提供 AOP 配置  -->
    <aop:config>

         <aop:aspect ref="CatAdvices">
            <!-- 在 包名中使用 .. 表示 多层路径  -->
            <!-- 在 () 之前中使用 * 表示 某个类中的所有方法  -->
            <!-- 在 参数列表中使用 .. 表示 任意多个参数 ( 可以是 零个、一个、多个)  -->
            <!-- 在 参数列表中使用 * 表示 至少有一个参数 ( 可以是 一个 或 多个)  -->
            <aop:pointcut id="pc" expression="execution(* com..schema.Cat.*(..))"/>

            <aop:before pointcut-ref="pc" method="before"/>

            <aop:around pointcut-ref="pc" method="around"/>

            <aop:after-returning pointcut-ref="pc" method="afterReturn" returning="returnValue"/>

            <aop:after-throwing pointcut-ref="pc" method="afterThrow" throwing="ex"/>

            <aop:after pointcut-ref="pc" method="after"/>
        </aop:aspect>
    </aop:config>


</beans>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值