Spring实战系列文章:
Spring实战 | Spring IOC不能说的秘密?
国庆中秋特辑系列文章:
国庆中秋特辑(八)Spring Boot项目如何使用JPA
国庆中秋特辑(七)Java软件工程师常见20道编程面试题
国庆中秋特辑(六)大学生常见30道宝藏编程面试题
国庆中秋特辑(五)MySQL如何性能调优?下篇
国庆中秋特辑(四)MySQL如何性能调优?上篇
国庆中秋特辑(三)使用生成对抗网络(GAN)生成具有节日氛围的画作,深度学习框架 TensorFlow 和 Keras 来实现
国庆中秋特辑(二)浪漫祝福方式 使用生成对抗网络(GAN)生成具有节日氛围的画作
国庆中秋特辑(一)浪漫祝福方式 用循环神经网络(RNN)或长短时记忆网络(LSTM)生成祝福诗词
Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架的一个重要模块。
Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架的一个重要模块,用于提供声明式的事务管理、日志记录、性能监控等功能。Spring AOP 底层依赖于 AspectJ 实现,可以与 Spring 框架无缝集成,提供一种更加简单、直观的方式来处理企业应用中的常见问题。
以下通过一个简单的案例来演示 Spring AOP 的使用。
<beans xmlns="" xmlns:xsi="" xmlns:aop="" xsi:schemaLocation=" .xsd .xsd"><!-- 定义目标类 --> <bean id="target" class=ample.TargetClass"></bean><!-- 定义切面类 --> <bean id="aspect" class=ample.AspectClass"></bean><!-- 开启自动代理 --> <aop:config proxy-target-class="true"> <!-- 指定切入点表达式 --> <aop:aspect ref="aspect"> <aop:before pointcut="execution(* ample.TargetClass.*(..))" method=ample.AspectClass.beforeAdvice"></aop:before> <aop:after pointcut="execution(* ample.TargetClass.*(..))" method=ample.AspectClass.afterAdvice"></aop:after> </aop:aspect> </aop:config>
</beans>
ample;
public class TargetClass { public int doAdd(int a, int b) { System.out.println("TargetClass doAdd method called"); return a + b; }public int doSubtract(int a, int b) { System.out.println("TargetClass doSubtract method called"); return a - b; }
}
ample;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
public class AspectClass { @Before("execution(* ample.TargetClass.*(..))") public void beforeAdvice(JoinPoint joinPoint) { System.out.println("Before advice: " + Signature().getName()); }@After("execution(* ample.TargetClass.*(..))") public void afterAdvice(JoinPoint joinPoint) { System.out.println("After advice: " + Signature().getName()); }
}
ample;
import t.ApplicationContext;
import t.support.ClassPathXmlApplicationContext;
public class TestClass { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(l"); TargetClass target = (TargetClass) Bean("target");int result1 = target.doAdd(2, 3); int result2 = target.doSubtract(5, 2);System.out.println("Result 1: " + result1); System.out.println("Result 2: " + result2); }
}
运行测试类,输出结果如下:
TargetClass doAdd method called
Before advice: doAdd
After advice: doAdd
Result 1: 5
TargetClass doSubtract method called
Before advice: doSubtract
After advice: doSubtract
Result 2: 3
从输出结果可以看出,在目标方法执行前和执行后分别执行了 beforeAdvice 和 afterAdvice 方法,说明 Spring AOP 已经成功实现了对目标方法的增强。
JDK 动态代理和 CGLIB 动态代理。JDK 动态代理是基于接口实现的,而 CGLIB 动态代理是基于类实现的。这两种代理方式在性能上有一定的差别,JDK 动态代理更适合用于接口较多的场景,而 CGLIB 动态代理则更适合用于类较多的场景。
ample.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {@Pointcut("execution(* ample.service.*.*(..))") public void serviceMethods() { }@Before("serviceMethods()") public void logBefore(JoinPoint joinPoint) { System.out.println("Before method: " + Signature().getName()); }@AfterReturning(pointcut = "serviceMethods()", returning = "result") public void logAfterReturning(JoinPoint joinPoint, Object result) { System.out.println("After returning method: " + Signature().getName()); System.out.println("Result: " + result); }
}
ample.service;
import org.springframework.stereotype.Service;
@Service
public class TargetService {public String sayHello(String name) { System.out.println("Hello, " + name); return "Hello, " + name; }
}
ample;
import t.annotation.ComponentScan;
import t.annotation.Configuration;
import t.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {ample.aspect", ample.service"})
public class AppConfig {
}
ample;
import t.ApplicationContext;
import t.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class Test {public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); TargetService targetService = Bean(TargetService.class); String result = targetService.sayHello("World"); System.out.println("Result: " + result); }
}
运行测试类,你将看到目标方法被切面增强的日志输出。这个示例展示了如何使用 Spring AOP JDK 动态代理实现简单的日志切面,以记录目标方法执行的前后状态。这有助于实现代码的重用和提高可维护性。
ample.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {@Pointcut("execution(* ample.service.*.*(..))") public void serviceMethods() { }@Before("serviceMethods()") public void logBefore(JoinPoint joinPoint) { System.out.println("Before method: " + Signature().getName()); }@AfterReturning(pointcut = "serviceMethods()", returning = "result") public void logAfterReturning(JoinPoint joinPoint, Object result) { System.out.println("After returning method: " + Signature().getName()); System.out.println("Result: " + result); }
}
ample.service;
import org.springframework.stereotype.Service;
@Service
public class TargetService {public String sayHello(String name) { System.out.println("Hello, " + name); return "Hello, " + name; }
}
ample;
import t.annotation.ComponentScan;
import t.annotation.Configuration;
import t.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {ample.aspect", ample.service"})
public class AppConfig {
}
ample;
import t.ApplicationContext;
import t.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class Test {public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); TargetService targetService = Bean(TargetService.class); String result = targetService.sayHello("World"); System.out.println("Result: " + result); }
}
运行测试类,你将看到目标方法被切面增强的日志输出。这有助于实现代码的重用和提高可维护性。
需要注意的是,CGLIB 动态代理需要 TargetService 类实现 equals() 和 hashCode() 方法,否则会报错。这是因为 CGLIB 需要生成目标类的代理类,而如果 TargetService 类没有实现 equals() 和 hashCode() 方法,那么生成的代理类将无法正确处理目标类的对象。
本文发布于:2024-01-27 19:39:49,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063555872232.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |