基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)

本文详细介绍了AOP概念,包括AspectJ的概念、Advice(通知)的作用、Jointpoint(连接点)与Pointcut(切入点)的应用,展示了如何通过AspectJ实现不同类型的通知,如前置通知、后置通知等,并提供了Spring Boot中配置AOP的步骤实例。
摘要由CSDN通过智能技术生成

AOP概念
AOP是Aspect Oriented Programming的缩写,即『面向切面编程』。它和我们平时接触到的OOP都是编程的不同思想,OOP,即『面向对象编程』,它提倡的是将功能模块化,对象化,而AOP的思想,则不太一样,它提倡的是针对同一类问题的统一处理,当然,我们在实际编程过程中,不可能单纯的安装AOP或者OOP的思想来编程,很多时候,可能会混合多种编程思想,大家也不必要纠结该使用哪种思想,取百家之长,才是正道

AspectJ
AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex,但目前最好、最方便的,依然是AspectJ。


Advice(通知)
注入到class文件中的代码。典型的 Advice 类型有 before、after 和 around,分别表示在目标方法执行之前、执行后和完全替代目标方法执行的代码。 除了在方法中注入代码,也可能会对代码做其他修改,比如在一个class中增加字段或者接口。

Joint point(连接点)
程序中可能作为代码注入目标的特定的点,例如一个方法调用或者方法入口。

Pointcut(切入点)
告诉代码注入工具,在何处注入一段特定代码的表达式。例如,在哪些 joint points 应用一个特定的 Advice。切入点可以选择唯一一个,比如执行某一个方法,也可以有多个选择,比如,标记了一个定义成@DebguTrace 的自定义注解的所有方法。

AspectJ提供不同类型的通知,分别为:
@Before 前置通知,相当于BeforeAdvice
@AfterReturning 后置通知,相当于AfterReturningAdvice
@Around 环绕通知,相当于MethodInterceptor
@AfterThrowing异常抛出通知,相当于ThrowAdvice
@After 最终final通知,不管是否异常,该通知都会执行

1:引入aspectj依赖

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

 

2:新建一个User类

 

public class User {
    public void add(){
        System.out.println("add方法");
    }
}

 

3:新建一个UserProxy类,被增强的一个类,

Before方法上加上@Before注解,配置切入点表达式,
*表示所有修饰符类型,后面加一个空格 

接着后面上全路径和方法名,最后..表示参数

@Component
@Aspect //表示生成一个代理对象
public class UserProxy {

    //前置通知
    //@Before注解表示作为前置通知
    @Before("execution(* com.example.wzy.demo.aop.User.add(..))")
    public void before(){
        System.out.println("before方法");
    }
}

 

 

4:新建一个bean9.xml

首先加上context和aop的名称空间

接着配置开启组件扫描

<context:component-scan base-package="com.example.wzy.demo.aop"></context:component-scan>

com.example.wzy.demo.aop是全路径,表示扫描这个包

 

还有添加

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

表示开启Aspect生成代理对象,就是去类上找有没有@Aspect注解,有的话就把这个对象生成一个代理对象

 

5:最后添加一个测试类

 

6:输出结果,这就是前置通知,在方法执行之前执行

 

 

 

 

@Component
@Aspect //表示生成一个代理对象
public class UserProxy {

    //前置通知
    //@Before注解表示作为前置通知
    @Before("execution(* com.example.wzy.demo.aop.User.add(..))")
    public void before() {
        System.out.println("before方法");
    }

    //后置通知,最终通知,方法执行之后执行,有异常也会执行
    @After("execution(* com.example.wzy.demo.aop.User.add(..))")
    public void after() {
        System.out.println("after方法");
    }

    //后置通知(返回通知)方法返回结果之后执行,有异常不执行
    @AfterReturning("execution(* com.example.wzy.demo.aop.User.add(..))")
    public void afterReturning() {
        System.out.println("AfterReturning");
    }

    //异常通知
    @AfterThrowing("execution(* com.example.wzy.demo.aop.User.add(..))")
    public void afterThrowing() {
        System.out.println("AfterThrowing");
    }

    //环绕通知
    @Around("execution(* com.example.wzy.demo.aop.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知之前");
        proceedingJoinPoint.proceed();
        //被增强的方法执行
        System.out.println("环绕通知之后");
    }
}

 

 

 

 

优化:

相同的切入点抽取,下面的都是重复的,可以提取出来,如下图

execution(* com.example.wzy.demo.aop.User.add(..))

 

 

比如对User的add方法需要两个增强类,那么使用

@Order()注解可以,里面的数字越小表示先执行

 

看下执行结果

 

 

 

 

 

使用下xml配置文件配置

新建Book类和BookProxy类

public class Book {
    public void buy(){
        System.out.println("buy*********");
    }
}

public class BookProxy {
    public void before(){
        System.out.println("before**********");
    }
}

 

2:新建bean.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">
    <!--名称空间-->

    <!--创建对象-->
    <bean id="book" class="com.example.wzy.demo.aopxml.Book"></bean>

    <bean id="bookProxy" class="com.example.wzy.demo.aopxml.BookProxy"></bean>

    <!--配置aop增强-->
    <aop:config>
        <!--切入点-->
    <aop:pointcut id="p" expression="execution(* com.example.wzy.demo.aopxml.Book.buy(..))"/>
        <!--配置切面-->
        <aop:aspect ref="bookProxy">
            <!--增强作用在具体的方法上-->
            <aop:before method="before" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>
</beans>

 

新建测试类

 

 @Test
    public void test2(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean10.xml");
        Book book = ac.getBean("book", Book.class);
        book.buy();
    }

执行结果

配置的是前置通知,所以先输出before再输出buy

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值