切面编程

Posted jiyukai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了切面编程相关的知识,希望对你有一定的参考价值。

一、XML实现AOP编程

  spring提供了注解的形式实现aop编程,同时也提供xml配置的形式实现,形式不同,最终实现的效果是一致的,下面进行xml实现aop编程的demo具体实现

  步骤1.编写切面和切入点

package com.jyk.spring.aop2;

import org.aspectj.lang.ProceedingJoinPoint;

public class UserAop {
    
    //前置通知,执行目标方法前执行
    public void begin()
    {
        System.out.println("开启事务");
    }
    
    //后置通知,执行目标方法后执行
    public void commit()
    {
        System.out.println("结束事务");
    }
    
    //返回后通知,目标方法调用结束后执行,出现异常不执行
    public void afterRunning()
    {
        System.out.println("目标方法调用结束后执行");
    }
    
    //异常通知,目标方法调用发生异常时执行
    public void throwException()
    {
        System.out.println("执行目标方法出现了异常");
    }
    
    //环绕通知,环绕目标方法执行
    public void arround(ProceedingJoinPoint pj)throws Throwable
    {
        System.out.println("环绕前");
        //执行目标方法
        pj.proceed();
        System.out.println("环绕后");
    }
}

  步骤2.编写业务接口和实现

package com.jyk.spring.aop2;

public interface UserInterface {

    public void add();
    
    public void delete();
}
package com.jyk.spring.aop2;

public class UserImpl implements UserInterface{
    
    @Override
    public void add() {
        System.out.println("核心业务1");
    }

    @Override
    public void delete() {
        System.out.println("核心业务2");
    }
}

  步骤3.在配置文件中将切面和业务实现类加入IOC容器,并配置切入点表达式

<?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" 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
        ">

    <!-- 将切面类加入IOC容器 -->
    <bean id="userAop" class="com.jyk.spring.aop2.UserAop"></bean>

    <!-- 将业务实现类加入IOC容器 -->
    <bean id="userImpl" class="com.jyk.spring.aop2.UserImpl"></bean>

    <!-- Aop配置 -->
    <aop:config>
        <!-- 定义一个切入点表达式: 拦截哪些方法 -->
        <!-- com.jyk.spring.aop2.*.*(..)意为拦截该包下所有类的所有方法 -->
        <aop:pointcut expression="execution(* com.jyk.spring.aop2.*.*(..))"
            id="pt" />
        <!-- 切面 -->
        <aop:aspect ref="userAop">
            <!-- 环绕通知 -->
            <aop:around method="arround" pointcut-ref="pt" />
            <!-- 前置通知: 在目标方法调用前执行 -->
            <aop:before method="begin" pointcut-ref="pt" />
            <!-- 后置通知: -->
            <aop:after method="commit" pointcut="execution(* com.jyk.spring.aop2.*.*(..))" />
            <!-- 返回后通知 -->
            <aop:after-returning method="afterRunning"
                pointcut-ref="pt" />
            <!-- 异常通知 -->
            <aop:after-throwing method="throwException"
                pointcut-ref="pt" />
        </aop:aspect>
    </aop:config>
</beans> 

  步骤4.验证结果,结果参见切面编程(二),效果与注解实现一致。

ApplicationContext ac = new ClassPathXmlApplicationContext("aop_xml.xml");
    
    //目标对象有实现接口,Spring会默认使用JDK代理
    @Test
    public void testJDK()
    {
        UserInterface ui = (UserInterface) ac.getBean("userImpl");
        System.out.println(ui.getClass());
        ui.add();
        ui.delete();
    }

技术分享图片

二、切入点表达式

  切入点表达式的使用丰富多样,可以对指定的“方法”进行拦截;  从而给指定的方法所在的类生层代理对象,下面简单介绍常见的切入点表达式

<!-- Aop配置 -->
    <aop:config>
        
        <!-- 定义一个切入点表达式: 拦截哪些方法 -->
        <aop:pointcut expression="execution(* com.jyk.spring.aop2.*.*(..))" id="pt"/>
        
        <!-- 【拦截所有public方法】 -->
        <aop:pointcut expression="execution(public * *(..))" id="pt"/>
        
        <!-- 【拦截所有save开头的方法 】 -->
        <aop:pointcut expression="execution(* add*(..))" id="pt"/>
        
        <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
        <aop:pointcut expression="execution(public * com.jyk.spring.aop2.UserImpl.add(..))" id="pt"/>
        
        <!-- 【拦截指定类的所有方法】 -->
        <aop:pointcut expression="execution(* com.jyk.spring.aop2.UserImpl.*(..))" id="pt"/>
        
        <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
        <aop:pointcut expression="execution(* com.jyk.spring..*.*(..))" id="pt"/>
        
        <!-- 【多个表达式】 -->
        <aop:pointcut expression="execution(* com.jyk.spring.aop2.UserImpl.add()) || execution(* com.jyk.spring.aop2.StudentImpl.add())" id="pt"/>
        <aop:pointcut expression="execution(* com.jyk.spring.aop2.UserImpl.add()) or execution(* com.jyk.spring.aop2.StudentImpl.add())" id="pt"/>
        
        <!-- 【取非值】 -->
        <aop:pointcut expression="!execution(* com.jyk.spring.aop2.UserImpl.add())" id="pt"/>
        <aop:pointcut expression=" not execution(* com.jyk.spring.aop2.UserImpl.add())" id="pt"/>
        
        <!-- 切面 -->
        <aop:aspect ref="aop">
            <!-- 环绕通知 -->
            <aop:around method="around" pointcut-ref="pt"/>
        </aop:aspect>
    </aop:config>

以上是关于切面编程的主要内容,如果未能解决你的问题,请参考以下文章

AOP 面向切面编程

java怎么运用切面编程生成日志

Spring的AOP面向切面编程

面向切面编程

面向切面编程

Spring面向切面编程