`

自定义注解结合切面和spel表达式

阅读更多

    在我们的实际开发中可能存在这么一种情况,当方法参数中的某些条件成立的时候,需要执行一些逻辑处理,比如输出日志。而这些代码可能都是差不多的,那么这个时候就可以结合自定义注解加上切面加上spel表达式进行处理。就比如在spring中我们可以使用@Cacheable(key="#xx")实现缓存,这个#xx就是一个spel表达式。

需求:我们需要将service层方法中方法的某个参数的值大于0.5的方法,输出方法执行日志。(需要了解一些spel表达式的语法

实现步骤

      1、自定义一个注解Log

      2、自定义一个切面,拦截所有方法上存在@Log注解修饰的方法

      3、写一个service层方法,方法上标注@Log注解

难点

      在切面中需要拿到具体执行方法的方法名,可以使用spring提供的LocalVariableTableParameterNameDiscoverer来获取到

 

一、自定义一个注解

    注意:注解中的spel的值是必须的,且spel表达式返回的结果应该是一个布尔值

/**
 * 记录日志信息,当spel表但是中的值为true时,输出日志信息
 * 
 * @描述
 * @作者 huan
 * @时间 2017年10月2日 - 上午10:25:39
 */
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
	String spel();
	String desc() default "描述";
}

 二、自定义一个service类,在需要拦截的方法上加上@Log注解
   

三、写一个自定义切面

    注意一下解析spel表达式中context的设值即可

/**
 * 日志切面,当条件满足时输出日志.
 * 
 * @描述
 * @作者 huan
 * @时间 2017年10月2日 - 上午10:32:16
 */
@Component
@Aspect
public class LogAspect {
	ExpressionParser parser = new SpelExpressionParser();
	LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
	@Around("@annotation(log)")
	public Object invoked(ProceedingJoinPoint pjp, Log log) throws Throwable {
		Object[] args = pjp.getArgs();
		Method method = ((MethodSignature) pjp.getSignature()).getMethod();
		String spel = log.spel();
		String[] params = discoverer.getParameterNames(method);
		EvaluationContext context = new StandardEvaluationContext();
		for (int len = 0; len < params.length; len++) {
			context.setVariable(params[len], args[len]);
		}
		Expression expression = parser.parseExpression(spel);
		if (expression.getValue(context, Boolean.class)) {
			System.out.println(log.desc() + ",在" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "执行方法," + pjp.getTarget().getClass() + "." + method.getName() 
                        + "(" + convertArgs(args) + ")");
		}
		return pjp.proceed();
	}
	private String convertArgs(Object[] args) {
		StringBuilder builder = new StringBuilder();
		for (Object arg : args) {
			if (null == arg) {
				builder.append("null");
			} else {
				builder.append(arg.toString());
			}
			builder.append(',');
		}
		builder.setCharAt(builder.length() - 1, ' ');
		return builder.toString();
	}
}

 四、pom文件的依赖

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

 五、测试。
   

 

六、增加内容:

1、当我们想在自己写的spel表达式中调用spring bean 管理的方法时,如何写。spel表达式支持使用 @来引用bean,但是此时需要注入BeanFactory

 

 


 
 

  • 大小: 38.6 KB
  • 大小: 130.9 KB
  • 大小: 21.8 KB
分享到:
评论
2 楼 huan1993 2018-05-01  
xiaonan830203 写道
太好了,网上找了1天都没找到的解决方案,在您这找到了,万分感谢了

有帮助就行。
1 楼 xiaonan830203 2018-04-28  
太好了,网上找了1天都没找到的解决方案,在您这找到了,万分感谢了

相关推荐

    spring-boot-annotation-spel.zip

    通过这种方式,我们可以利用Spring Boot的自定义注解和SPEL表达式实现高度灵活的逻辑控制,而无需修改大量硬编码的条件判断。这种能力在设计复杂系统或者需要动态配置的场景下尤为有用。 压缩包中的文件可能包含...

    Spring_SpEl表达式使用用例

    综上所述,Spring SpEL表达式为开发者提供了强大的表达能力,使得在运行时可以更加灵活地控制和操作对象。通过理解和熟练运用SpEL,我们可以编写出更具有弹性的Spring应用程序。在实际项目中,应根据需求选择合适的...

    spring spEL 表达式详解

    在Spring框架中,SpEL被广泛应用于配置文件、注解以及AOP(面向切面编程)中,使得动态数据绑定和复杂逻辑判断变得简单易行。下面我们将深入探讨SpEL的主要特性和用法。 1. **基础语法** - 属性访问:`#{T...

    Spring开发手册_表达式语言_API中文版

    SpEL 在 Spring 的许多核心功能中扮演着关键角色,如 Bean 的装配、AOP(面向切面编程)的切入点定义等。 **1. SpEL 基本概念** - **表达式**: SpEL 支持多种类型的表达式,如属性访问、方法调用、算术运算、比较...

    在自定义spring aop中使用el获取拦截方法的变量值。

    标题中的“在自定义Spring AOP中使用EL获取拦截方法的变量值”指的是在Spring的面向切面编程(AOP)中,通过Expression Language(EL,表达式语言)来访问被拦截方法的局部变量值。这通常涉及到Spring的代理机制、...

    pring3表达式语言共13页.pdf.zip

    - **AOP**:在切面定义中,SpEL可以用来决定切面何时应用或如何应用。 - **数据绑定**:在Web表单和模型对象之间,SpEL用于绑定和验证数据。 8. **函数和方法** SpEL允许直接调用对象的方法,甚至可以创建新的...

    common.zip

    本项目涉及的主题是“基于Spring Boot的方法耗时自定义注解和切面”,这是一个用于性能监控和日志记录的技术实践。我们将深入探讨如何创建自定义注解以及如何利用AOP(面向切面编程)来实现方法执行耗时的跟踪。 ...

    基于IDEA的SSH项目之四:简单的切面应用---程序包

    在这个主题中,我们将探讨如何在IntelliJ IDEA(IDEA)集成开发环境中实现基于Spring、Struts和Hibernate(SSH)的项目,并重点讲解Spring框架中的切面编程(AOP)。SSH是一种流行的企业级Java开发框架,它允许...

    day38 13-Spring的Bean的属性的注入:SpEL注入

    同时,它与Spring的其他特性,如AOP(面向切面编程)和Bean的生命周期管理,无缝集成,提供了高度灵活和强大的依赖注入解决方案。 在实际开发中,结合`@ConfigurationProperties`和SpEL,我们可以实现更高级的配置...

    spring-aop和注解的实例

    4. **关联切面和通知**:使用`@Before`, `@After`, 等注解直接在通知方法上,或者在`@Aspect`类内部定义一个`@Pointcut`,然后在`@Before`, `@After`等注解中引用这个切入点表达式,将通知与切入点关联起来。...

    spring扩展点测试示例代码

    切面可以通过自定义注解(如`@Transactional`)或配置XML来定义,实现代码的解耦。 2. **Bean后处理器(Bean Post Processors)**: 这是Spring框架中的另一个扩展点,可以在bean初始化前后执行自定义逻辑。例如,...

    spring 注解注意事项、值的接受传递不同方式

    6. **SpEL(Spring Expression Language)**:Spring表达式语言允许在注解中使用复杂的表达式来动态计算值。例如,`@Value("#{'${my.property}' + 'world'}")`会将属性值与字符串"world"连接。 7. **注解参数**:...

    注解小例子

    5. 如果需要AOP功能,可以创建一个切面类,并添加@Aspect和@Pointcut注解。 6. 在控制器类上使用@RequestMapping注解处理HTTP请求。 7. 配置Spring XML文件(可选),如果你不完全依赖注解配置。 8. 使用Eclipse的...

    Spring AOP切面编程简介

    Spring框架中的AOP模块提供了实现这一目标的工具,使得开发者可以轻松地创建和使用切面。 AOP的核心概念包括以下几个部分: 1. **切面(Aspect)**:切面是AOP的核心,它包含了业务逻辑和横切关注点。在Spring AOP...

    springmvc注解开发jar包

    - `spring-expression.jar`:支持Spring表达式语言(SpEL),用于运行时查询和操作对象图。 6. **其他相关库**: - `jstl.jar` 和 `javax.servlet-api.jar`:用于JSP页面和Servlet API。 - `commons-logging.jar...

    spring 注解

    Spring框架是Java企业级应用开发中的核心库,它提供了一个全面的编程和配置模型,特别强调依赖注入(DI)和面向切面编程(AOP)。 在Spring中,注解主要分为以下几类: 1. **组件扫描注解**: - `@Component`:这...

    pring注解相关完整讲述共17页.pdf.zip

    12. **AOP(面向切面编程)**:Spring AOP允许我们在不修改源代码的情况下,对方法进行拦截,实现如日志记录、权限验证等功能。@Aspect、@Before、@After、@Around和@Pointcut是AOP中常用的注解。 13. **Spring ...

    spring 中特殊bean用法

    特殊Bean用法主要涉及Spring提供的多种高级特性,包括但不限于工厂方法、 prototype scope、AOP代理、SpEL表达式、条件注解等。下面将详细介绍这些特殊用法。 1. **工厂方法**: 在某些情况下,我们可能需要自定义...

Global site tag (gtag.js) - Google Analytics