【框架】[Spring]AOP拦截-使用切点:AspectJExpressionPointcut-切点语言

简介: 【框架】[Spring]AOP拦截-使用切点:AspectJExpressionPointcut-切点语言

用AspectJExpressionPointcut实现的切点比JdkRegexpMethodPointcut实现切点的好处就是,在设置切点的时候可以用切点语言来更加精确的表示拦截哪个方法!

可以精确到返回参数,参数类型,方法名。

当然,也可以模糊匹配。

这里用纯Java的方式和配置xml的方法都来演示一遍。

需要的包什么的就不解释了,如不动,请参考前面的。

首先,准备好原型对象Person

package cn.hncu.spring3x.aop.aspectj;
public class Person {
    public int run(){
       System.out.println("我在run...");
       return 0;
   }
   public void run(int i){
       System.out.println("我在run...<"+i+">");
   }
   public void say(){
       System.out.println("我在say...");
   }
   public void sayHi(String name){
       System.out.println("Hi,"+name+",你好");
   }
   public int say(String name, int i){
       System.out.println(name+ "----"+ i);
       return 0;
   }
}

然后,用两种方式来拦截这个对象。

纯Java方式实现

4步曲:

1、声明出代理工厂。

2、设置切点

3、设置通知

4、为工厂添加切面

请记住:切面=切点+通知

AspectjDemo

package cn.hncu.xmlImpl.aspectj;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class AspectjDemo {
    @Test
    public void demo(){
        ProxyFactoryBean factory = new ProxyFactoryBean();
        factory.setTarget(new Person());
        //声明一个aspectj切点
        AspectJExpressionPointcut cut = new AspectJExpressionPointcut();
        //设置需要拦截的方法-用切点语言来写
        cut.setExpression("execution( int cn.hncu.xmlImpl.aspectj.Person.run() )");//拦截:空参返回值为int的run方法
        Advice advice = new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("放行前拦截...");
                Object obj = invocation.proceed();//放行
                System.out.println("放行后拦截...");
                return obj;
            }
        };
        //切面=切点+通知
        Advisor advisor = new DefaultPointcutAdvisor(cut,advice);
        factory.addAdvisor(advisor);
        Person p = (Person) factory.getObject();
        p.run();
        p.run(10);
        p.say();
        p.sayHi("Jack");
        p.say("Tom", 666);
    }
}

运行结果:

image.png

切点语言:

AspectJExpressionPointcut对象在调用:

setExpression时,这个方法的参数就是使用切点语言的。

切点语言格式:

execution ( 返回类型 方法路径.方法名(参数) )

例子:

//声明一个aspectj切点
        AspectJExpressionPointcut cut = new AspectJExpressionPointcut();
cut.setExpression("execution( int cn.hncu.xmlImpl.aspectj.Person.run() )");//拦截:空参返回值为int的run方法
cut.setExpression("execution( void cn.hncu.xmlImpl.aspectj.Person.*() )");//拦截:空参空返回值的任意方法
cut.setExpression("execution (void cn.hncu.xmlImpl.aspectj.Person.*(String))");//拦截:只有1个String类型参数,空返回值的任意方法
cut.setExpression("execution( void cn.hncu.xmlImpl.aspectj.Person.*(*) )");//拦截:有1个参数(类型不限),空返回值的任意方法
cut.setExpression("execution( void cn.hncu.xmlImpl.aspectj.Person.*(*,*) )");//拦截:有2个参数(类型不限),空返回值的任意方法
cut.setExpression("execution( void cn.hncu.xmlImpl.aspectj.Person.*(..) )");//拦截:任意(个数和类型)参数,空返回值的任意方法
cut.setExpression("execution( int cn.hncu.xmlImpl.aspectj.Person.*(*,..) )");//拦截:至少有1个参数(类型不限),返回值类型是int的任意方法
cut.setExpression("execution( * cn.hncu.xmlImpl.aspectj.Person.*(*,..) )");//拦截:至少有1个参数(类型不限),返回值类型任意的方法
cut.setExpression("execution( * cn.hncu..*son.*(*,..) )");//拦截:cn.hncu包下,类名以"son"结束,至少有1个参数(类型不限),返回值类型任意的方法

里面的参数是可以匹配正则表达式的。

“.”代表除\r\n外的任意字符。

“*”代表0个或多个。

由于切点语言无法定义指定的多个返回值,所以,例如:

如果需要拦截void和int返回值方法,则可以通过定义2个切点解决。

xml配置AOP拦截

AroundAdvice

package cn.hncu.xmlImpl.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class AroundAdvice implements MethodInterceptor{
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("前面拦截....");
        Object resObj = invocation.proceed();//放行
        System.out.println("后面拦截.....");
        return resObj;
    }
}

配置文件

<?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:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    <!-- 自动代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
    <bean id="p" class="cn.hncu.xmlImpl.aspectj.Person"></bean>
    <!-- 切面=切点+通知 (把切点和通知写成内部bean)-->
    <bean id="cut" class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
        <!-- 拦截:cn.hncu包下,类名以"son"结束,至少有1个参数(类型不限),返回值类型任意的方法 -->
      <property name="expression" value="execution( * cn.hncu..*son.*(*,..) )"></property>    
    </bean>
    <bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
       <property name="pointcut" ref="cut"></property>
       <property name="advice">
            <bean id="advice" class="cn.hncu.xmlImpl.aspectj.AroundAdvice"></bean>
       </property>
    </bean>
</beans>

中间也可以这样配置:

<!-- 自动代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
    <bean id="p" class="cn.hncu.xmlImpl.aspectj.Person"></bean>
    <!-- 切面=切点+通知 (※※采用面向切点语言进行配置切面)-->
    <bean id="advisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
       <property name="expression" value="execution( * cn.hncu..*son.*(*,..) )"></property>
       <property name="advice">
            <bean id="advice" class="cn.hncu.xmlImpl.aspectj.AroundAdvice"></bean>
       </property>
    </bean>

测试类:

package cn.hncu.xmlImpl.aspectj;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AspectjXmlDemo {
    @Test
    public void demo1(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/aspectj/aspectj.xml");
        Person p = ctx.getBean(Person.class);
        p.run();
        p.run(10);
        p.say();
        p.sayHi("Jack");
        p.say("Tom", 666);
    }
}

测试结果

image.png

在本例:xml配置与纯Java方式相比,即把通过Java代码new出来的对象,通过xml配置来造对象。

如果是开发项目,用Spring的框架,我们的一些通过xml注入的对象就只需要依赖xml文件了。

而依赖xml的依赖不叫依赖,也就是独立了。

目录
打赏
0
0
0
0
988
分享
相关文章
Spring框架初识
Spring 是一个分层的轻量级开源框架,核心功能包括控制反转(IOC)和面向切面编程(AOP)。主要模块有核心容器、Spring 上下文、AOP、DAO、ORM、Web 模块和 MVC 框架。它通过 IOC 将配置与代码分离,简化开发;AOP 提供了声明性事务管理等增强功能。
54 21
Spring框架初识
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
104 6
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
117 29
|
21天前
|
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
88 25
|
21天前
|
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
76 24
通过springboot框架创建对象(一)
在Spring Boot中,对象创建依赖于Spring框架的核心特性——控制反转(IoC)和依赖注入(DI)。IoC将对象的创建和管理交由Spring应用上下文负责,开发者只需定义依赖关系。DI通过构造函数、setter方法或字段注入实现依赖对象的传递。Spring Boot的自动配置机制基于类路径和配置文件,自动为应用程序配置Spring容器,简化开发过程。Bean的生命周期包括定义扫描、实例化、依赖注入、初始化和销毁回调,均由Spring容器管理。这些特性提高了开发效率并简化了代码维护。
Spring Boot中的日志框架选择
在Spring Boot开发中,日志管理至关重要。常见的日志框架有Logback、Log4j2、Java Util Logging和Slf4j。选择合适的日志框架需考虑性能、灵活性、社区支持及集成配置。本文以Logback为例,演示了如何记录不同级别的日志消息,并强调合理配置日志框架对提升系统可靠性和开发效率的重要性。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
87 8
理解和解决Spring框架中的事务自调用问题
事务自调用问题是由于 Spring AOP 代理机制引起的,当方法在同一个类内部自调用时,事务注解将失效。通过使用代理对象调用、将事务逻辑分离到不同类中或使用 AspectJ 模式,可以有效解决这一问题。理解和解决这一问题,对于保证 Spring 应用中的事务管理正确性至关重要。掌握这些技巧,可以提高开发效率和代码的健壮性。
144 13