文章目录
前言
基于Spring Cloud创建自定义注解,并根据该注解实现日志功能
一、创建自定义注解
创建一个自定义注解,用于标记需要记录业务日志的方法。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
String value() default "";
}
@Target
和 @Retention
是 Java 注解中的元注解,用于定义自定义注解的适用范围和保留策略。
当使用 @interface 关键字创建自定义注解时,需要在自定义注解的定义中使用这些元注解来指定注解的行为。
在这个示例中:
@Target(ElementType.METHOD)
表示自定义注解@Loggable
只能应用于方法上。@Retention(RetentionPolicy.RUNTIME)
表示该注解的保留策略是运行时,使得在运行时能够通过反射获取注解信息。
自定义注解 @Loggable
就被定义为只能应用于方法,并且它的信息在运行时可以被保留和获取。
二、创建切面类
创建一个切面类,用于拦截带有自定义注解的方法调用,并执行日志记录逻辑
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
private final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
@Before("@annotation(loggable) && within(your.package..*)")
public void beforeLoggableMethod(JoinPoint joinPoint, Loggable loggable) {
String methodName = joinPoint.getSignature().getName();
String logMessage = "Executing method: " + methodName;
if (!loggable.value().isEmpty()) {
logMessage += " - " + loggable.value();
}
logger.info(logMessage);
}
}
@Aspect
和@Component
都是Spring框架中的注解,但是它们的作用不同。@Aspect
注解用于标注一个类是一个切面类,切面类用于定义应用程序中的横切关注点,例如日志记录、事务管理、缓存等。切面类中的方法被称为切点方法,这些方法被Spring框架扫描到并执行。下面是@Aspect
注解的详细解释:
@Aspect
: 标注该类是一个切面类。@Component
: 标注该类是一个组件,表明该类需要被Spring容器管理。使用
@Aspect
注解时,需要同时使用@Component
注解,因为切面类也是一个组件,需要被Spring容器管理。在Spring框架中,使用@Component
注解标注的类会被Spring容器管理,容器会自动创建该类的实例并将其注册到容器中,当需要使用该组件时,容器会自动注入该组件到其他组件中。 另外,切面类可以使用@Pointcut
注解定义切点,使用@Before
、@After
、@AfterReturning
、@AfterThrowing
注解定义切点方法的执行顺序和执行方式。例如:@Aspect @Component public class MyAspect { @Pointcut("execution(* com.example.service.*.*(..))") public void myPointcut() {} @Before("myPointcut()") public void beforeMethod(JoinPoint joinPoint) { System.out.println("Before method execution"); } @After("myPointcut()") public void afterMethod(JoinPoint joinPoint) { System.out.println("After method execution"); } @AfterReturning("myPointcut()") public void afterReturningMethod(JoinPoint joinPoint, Object ret) { System.out.println("After returning method execution"); } @AfterThrowing(pointcut = "myPointcut()", throwing = "ex") public void onThrowing(JoinPoint joinPoint, Throwable ex) { System.out.println("After throwing method execution"); } }
上述代码定义了一个切面类
MyAspect
,其中定义了一个切点myPointcut
,使用@Before
、@After
、@AfterReturning
和@AfterThrowing
注解定义了切点方法的执行顺序和执行方式。在具体的切点方法执行时,可以根据需要调用不同的注解来执行不同的操作。@Component
注解用于标注一个类是一个组件,表明该类需要被Spring容器管理。在Spring框架中,使用@Component
注解标注的类会被Spring容器管理,容器会自动创建该类的实例并将其注册到容器中,当需要使用该组件时,容器会自动注入该组件到其他组件中。例如:@Component public class MyComponent { public void myMethod() { System.out.println("My component method execution"); } }
上述代码定义了一个组件类
MyComponent
,其中使用了@Component
注解,表明该类需要被Spring容器管理。在需要使用该组件的地方,可以使用@Autowired
注解来自动注入该组件。
三、配置Spring
在Spring Boot应用程序的配置中,确保已启用AOP以便切面能够生效。在 @SpringBootApplication
注解上添加 @EnableAspectJAutoProxy
注解来启用AOP。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication
@EnableAspectJAutoProxy
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
@EnableAspectJAutoProxy 是一个Spring Framework中的注解,用于启用基于AspectJ的AOP(面向切面编程)自动代理功能。当使用AOP时,可以将切面逻辑与业务逻辑分离,实现例如日志记录、事务管理等非业务逻辑的模块化。以下是关于 @EnableAspectJAutoProxy 的一些详细信息:
用途: @EnableAspectJAutoProxy 注解用于启用Spring容器中对基于AspectJ的AOP代理的支持。它会自动检测切面定义并在需要的时候自动创建代理。
工作原理: 当使用 @EnableAspectJAutoProxy 注解启用AOP代理时,Spring容器会自动识别切面类并为目标bean创建代理。这样,切面的逻辑将被织入到目标bean的方法调用中,实现预定的切面功能。
配置: 在Spring Boot应用程序中,一般只需在配置类(通常是主应用类)上添加 @EnableAspectJAutoProxy 注解,即可启用AOP功能。
适用情况: 使用 @EnableAspectJAutoProxy 适用于需要基于切面进行非业务逻辑的模块化的情况。例如,您可以在切面中实现日志记录、事务管理、安全验证等通用功能。
四、使用自定义注解
在业务类中使用自定义注解,以标记需要记录业务日志的方法。
package your.package;
import org.springframework.stereotype.Service;
@Service
public class YourService {
@Loggable("Custom log message")
public void doSomething() {
// Your business logic here
}
}
请将 your.package
替换为您的实际业务包路径。
在上述代码中,@Before("@annotation(loggable) && within(your.package..*)")
表示只有在带有 @Loggable
注解且位于指定包路径下的方法调用才会被拦截并记录日志。
这样,就可以基于Spring Cloud创建自定义注解,并根据注解实现某个包下所有的业务日志拦截功能。需要注意,这只是一个基本示例,需要根据具体项目需求进行更多的定制和扩展。