Spring简单的练习AspectJ,来完成aop-菜鸟一枚

Posted 名字真的很急用

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring简单的练习AspectJ,来完成aop-菜鸟一枚相关的知识,希望对你有一定的参考价值。

AOP,即面向切面编程,它是oop(面向对象编程)的一种补充,
在传统的业务处理代码中,通常会进行事务处理,日志记录等操作,虽然使用OOP可以通过组合的形式或者继承的方式来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码会分散到各个方法中。这样,如果想要关闭某个功能,或者进行修改,就必须要修改所有的相关方法。
为了解决这个问题,AOP思想随之产生,AOP采用横向抽取机制,将分散在各个方法中的重复代码抽取出来,然后在程序编译或者运行时,再将这些提前出来的代码应用到需要执行的地方。

AOP相关概念

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。

连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice

切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上

引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口

目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
原文链接:https://blog.csdn.net/MoreeVan/article/details/11977115

AspectJ开发;
它是一个基于java语言的aop框架,它提供了强大的AOP功能。使用AspectJ实现AOP有二种方式:一种是基于xml的声明式AspectJ,另一种是基于注解的声明式AspectJ。

接下来看代码。
在这里插入图片描述
这是我们进行增强处理代码

import java.util.Arrays;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

public class UserServiceLogger {
    private static final Logger log = Logger.getLogger(UserServiceLogger.class);
    //前置增强  JoinPoint 连接点
    public void before(JoinPoint jp) {
        log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
    }
    public void afterReturning(JoinPoint jp, Object result) {
        log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法返回值:" + result);
    }
}

这是我们需要增强处理的方法。

import org.springframework.stereotype.Service;

@Service
public class UserService {

   public String addUser(String name){

       System.out.println("添加用户 " + name);
       return "jim";
   }
}

配置我们的applicationcontext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!--suppress ALL -->
<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-3.2.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 声明增强方法所在的Bean -->
    <!-- 也就是定义切面 -->
    <bean id="theLogger" class="aop.UserServiceLogger"></bean>
    <!-- 配置切面 -->
    <aop:config>
        <!-- 定义切入点 -->
        <aop:pointcut id="pointcut"
            expression="execution(* com.service..*.*(..))" />
        <!-- 引用包含增强方法的Bean -->
        <aop:aspect ref="theLogger">
            <!-- 将before()方法定义为前置增强并引用pointcut切入点 -->
            <aop:before method="before" pointcut-ref="pointcut"></aop:before>
            <!-- 将afterReturning()方法定义为后置增强并引用pointcut切入点 -->
            <!-- 通过returning属性指定为名为result的参数注入返回值 -->
            <aop:after-returning method="afterReturning"
                pointcut-ref="pointcut" returning="result" />
        </aop:aspect>
    </aop:config>
    <!--扫描基础包-->
    <context:component-scan base-package="com.service" />
</beans>

最后是我们的测试类。

import com.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        // 通过ClassPathXmlApplicationContext实例化Spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        // 通过ApplicationContext的getBean()方法,根据id来获取bean的实例
        UserService u = (UserService) context.getBean("userService");
        u.addUser("张三");
    }
}

在这里插入图片描述

以上是关于Spring简单的练习AspectJ,来完成aop-菜鸟一枚的主要内容,如果未能解决你的问题,请参考以下文章

比较分析 Spring AOP 和 AspectJ 之间的差别

Spring详解------AspectJ 实现AOP

spring的aop怎么获取切点参数

[Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

[Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

译:在 Spring Boot 中使用 Spring AOP 和 AspectJ 来测量方法的执行时间