本文共 7932 字,大约阅读时间需要 26 分钟。
public interface LeviService {
public boolean problem1();
public boolean problem2();
} |
@Service public class LeviServiceImpl implements LeviService {
@Override public boolean problem1() { System.out.println("problem1 访问开始时间:" + System.currentTimeMillis());
System.out.println("执行业务逻辑。。。");
System.out.println("problem1 访问结束时间:" + System.currentTimeMillis()); return true; }
@Override public boolean problem2() { System.out.println("problem2 访问开始时间:" + System.currentTimeMillis());
System.out.println("执行业务逻辑。。。");
System.out.println("problem2 访问结束时间:" + System.currentTimeMillis()); return true; } } |
@Configuration @ComponentScan(value = "com.levi.spring.aop.levi01base") public class MainConfig {
/** * 传统OOP的问题:执行结果会发现每个方法都会去执行这个时间的方法,这样就造成了代码冗余以及难以维护。 */ public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
LeviService leviService = annotationConfigApplicationContext.getBean(LeviServiceImpl.class);
leviService.problem1(); leviService.problem2();
annotationConfigApplicationContext.close(); } } |
<!-- AOP切面 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.0.6.RELEASE</version> </dependency> |
与传统的OOP(Object Oraentd Programming)面向对象对比,传统的OOP开发中的代码逻辑是自上而下的,在这些自上而下的代码中会产生横切面的问题,而这些横切面又与主业务逻辑关系不大,但是会散落在代码的各个地方,造成难以维护。
AOP的编程思想就是把这些横切性的问题和主业务逻辑进行分离,从而起到了解耦的目的。比如在每一个Service或Controller方法上加上日志打印,那么就要在每个方法都加上这个打印了,而如果用AOP就可以直接定位到这个包,只要访问这个包下的方法就会统一执行这个日志打印。
public interface LeviService {
public boolean problem1(int i);
public boolean problem2();
public int myException(int i) throws Exception; } |
@Service public class LeviServiceImpl implements LeviService {
@Override public boolean problem1(int i) { // System.out.println("problem1 访问开始时间:" + System.currentTimeMillis());
System.out.println("执行业务逻辑。。。" + i);
// System.out.println("problem1 访问结束时间:" + System.currentTimeMillis()); return true; }
@Override public boolean problem2() { // System.out.println("problem2 访问开始时间:" + System.currentTimeMillis());
System.out.println("执行业务逻辑。。。");
// System.out.println("problem2 访问结束时间:" + System.currentTimeMillis()); return true; }
@Override public int myException(int i) throws Exception { System.out.println("执行业务逻辑。。。" + i); if(i == 5) { throw new Exception("抛出异常了..."); } return 1; } } |
/** * 日志切面: * @Before:在目标方法之前执行 * @After:在目标方法执行之后执行 * @AfterReturning:在目标方法返回之前执行 * @AfterThrowing:在目标方法抛出异常之后执行,如果异常在@Around捕捉了,那么就不会执行了 * @Around:在执行方法之前前后执行 */ @Aspect @Component public class LogAopAspects1 {
/** * 在目标方法开始之前执行 */ // @Before("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))") @Before("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))") public void before(JoinPoint joinpoint) { System.out.println("@Before:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs())); }
/** * 在目标方法执行完成之后执行 */ @After("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))") public void after(JoinPoint joinpoint) { System.out.println("@After:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs())); }
/** * 目标方法执行完成之后的返回 */ @AfterReturning(value="execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))",returning = "result") public void afterReturning(JoinPoint joinpoint,Object result) { System.out.println("@AfterReturning:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()) + " - 结果:" + result); }
/** * 目标方法抛出异常之后执行 */ @AfterThrowing(value="execution(public int com.levi.spring.aop.levi02aopbase.LeviService.myException(..))",throwing = "exception") public void afterThrowing(JoinPoint joinpoint,Exception exception) { System.out.println("@AfterThrowing:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs())); }
/** * 在一个方法之前和执行后的操作 */ @Around("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("@Around:调用执行方法之前的执行时间:" + System.currentTimeMillis());
try { proceedingJoinPoint.proceed(); //执行目标方法 } catch (Throwable e) { System.out.println("@Around:执行目标方法报错"); //抛出异常,验证@AfterThrowing // throw e; }
System.out.println("@Around:调用执行方法之后的执行时间:" + System.currentTimeMillis()); } } |
@Configuration @EnableAspectJAutoProxy @ComponentScan(value = "com.levi.spring.aop.levi02aopbase") public class MainConfig {
/** * Aop编程:与传统的OOP(Object Oraentd Programming)面向对象对比,传统的OOP开发中的代码逻辑是自上而下的, * 在这些自上而下的代码中会产生横切面的问题,而这些横切面又与主业务逻辑关系不大,但是会散落在代码的各个地方,造成难以维护。 * AOP的编程思想就是把这些横切性的问题和主业务逻辑进行分离,从而起到了解耦的目的。 * 比如在每一个Service或Controller方法上加上日志打印,那么就要在每个方法都加上这个打印了,而如果用AOP就可以直接定位 * 到这个包,只要访问这个包下的方法就会统一执行这个日志打印。 * * 1、定义好AOP切面类,并写好对应的切点(execution) * 2、将AOP切面类和业务类放入容器中(代码中:@Component、@Service) * 3、基于注解开启AOP,@EnableAspectJAutoProxy */ public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
/* * 首次执行会发现为什么AOP没有起作用。 * AOP是相当于一个Spring功能模块,要用这个功能模块要开启才行。 * 要在MainConfig中加上@EnableAspectJAutoProxy * * 加了@EnableAspectJAutoProxy发现还是不行。 * 还要在对应的AOP配置类中,标识说明这个类是AOP编程的类 * 在LogAopAspects1中加上@Aspect */
LeviService leviService = annotationConfigApplicationContext.getBean(LeviService.class); leviService.myException(3);
annotationConfigApplicationContext.close(); } } |
/** * 日志切面: * @Before:在目标方法之前执行 * @After:在目标方法执行之后执行 * @AfterReturning:在目标方法返回之前执行 * @AfterThrowing:在目标方法抛出异常之后执行,如果异常在@Around捕捉了,那么就不会执行了 * @Around:在执行方法之前前后执行 * * 〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓 * * LogAopAspects1的写法太麻烦了,如果每个方法都要这样写的话,是否又会出现大量的冗余,那样的话就也只是简化了一点冗余而已。 * LogAopAspects2的新写法 * @Pointcut:点切,指定点 */ @Aspect @Component public class LogAopAspects2 {
@Pointcut("execution(public int com.levi.spring.aop.levi02aopbase.LeviService.*(..))") public void pointCut() { System.out.println("@Pointcut"); };
/** * 在目标方法开始之前执行 */ // @Before("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))") @Before("pointCut()") public void before(JoinPoint joinpoint) { System.out.println("@Before:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs())); }
/** * 在目标方法执行完成之后执行 */ // @After("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))") @After("pointCut()") public void after(JoinPoint joinpoint) { System.out.println("@After:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs())); }
/** * 目标方法执行完成之后的返回 */ // @AfterReturning("execution(public boolean com.levi.spring.aop.levi02aopbase.LeviService.*(..))") @AfterReturning(value="pointCut()",returning = "result") public void afterReturning(JoinPoint joinpoint,Object result) { System.out.println("@AfterReturning:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs()) + " - 结果:" + result); }
/** * 目标方法抛出异常之后执行 */ // @AfterThrowing(value="execution(public void com.levi.spring.aop.levi02aopbase.LeviService.myException(..))",throwing = "exception") @AfterThrowing(value="pointCut()",throwing = "exception") public void afterThrowing(JoinPoint joinpoint,Exception exception) { System.out.println("@AfterThrowing:" + joinpoint.getSignature().getName() + " - 参数:" + Arrays.asList(joinpoint.getArgs())); }
/** * 在一个方法之前和执行后的操作 */ // @Around("execution(public void com.levi.spring.aop.levi02aopbase.LeviService.*(..))") @Around("pointCut()") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("@Around:调用执行方法之前的执行时间:" + System.currentTimeMillis());
try { proceedingJoinPoint.proceed(); //执行目标方法 } catch (Throwable e) { System.out.println("@Around:执行目标方法报错"); //抛出异常,验证@AfterThrowing // throw e; }
System.out.println("@Around:调用执行方法之后的执行时间:" + System.currentTimeMillis()); } } |
转载地址:http://zqmxi.baihongyu.com/