6.spring:AOP(注解)

本文内容纲要:6.spring:AOP(注解)

spring Aop

AOP面向切面编程,与OOP面向对象编程相辅相成

AOP中最基本的单元是切面

问题:

代码混乱:越来越多的业务需求(日志&验证)加入后,原有的业务方法急剧膨胀,每个方法在处理核心代码的同时还必须兼顾其他的多个关注点

代码分散,以日志为例,知识为了满足这一单一的需求,就不得不在代码块中里多次调用重复的日志代码,如果日志发生变化,必须修改所有的模块

简介:

AOP:面向切面编程,是一种新的方法,式传统OOP面向对象编程的补充

AOP主要编程对象是切面,而切面模块化横切的关注点

在应用AOP编程时,仍需要定义公共的功能,但可以明确定义的功能在哪,以什么方式应用,并且不必修改影响的类,这样横切关注点就被模块化到特殊的

对象(切面)里

AOP的好处:

->每个事物逻辑位于一个位置,代码不分散,便于维护

->业务模块化更简洁,只包含核心的业务代码

AOP术语:

切面(Aspect):横切关注点被模块化的特殊对象

通知(Advice):切换必须完成的工作

目标(Target):被通知的对象

代理(Proxy):向目标对象应用的通知之后创建的对象

连接点(Joinpoint):程序执行的特定位置

切点(pointcut):每个类都有若干个连接点,

AOP即使通过定位到特定的连接点

Image

每次做方法的时候,都在执行之前和之后都有相关的打印操作!

AtithmeticCalculator.java

public interface AtithmeticCalculator {

int add(int i,int j);

int sub(int i,int j);

int mul(int i,int j);

int div(int i,int j);

}

AtithmeticCalculatorImp.java

接口中方法的实现。

@Component

public class AtithmeticCalculatorImp implements AtithmeticCalculator{

public int add(int i, int j) {

int res = i + j;

return res;

}

public int sub(int i, int j) {

int res = i - j;

return res;

}

public int mul(int i, int j) {

int res = i * j;

return res;

}

public int div(int i, int j) {

int res = i / j;

return res;

}

}

LoggionAspect.java

切面类

//把这个类升级称为一个切面:返给到IOC容器中---->在声明为一个注解

@Order(2)

@Aspect

@Component

public class LoggionAspect {

@Before("execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))")

public void beforeMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

Object [] args = joinPoint.getArgs();

System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));

}

/**

* 在方法执行之后执行的代码. 无论该方法是否出现异常

*/

@After("execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))")

public void afterMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends");

}

/**

* 在方法法正常结束受执行的代码

* 返回通知是可以访问到方法的返回值的!

*/

@AfterReturning(value="execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))",

returning="result")

public void afterReturning(JoinPoint joinPoint, Object result){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends with " + result);

}

/**

* 在目标方法出现异常时会执行的代码.

* 可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码

*/

@AfterThrowing(value="execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))",throwing="e")

public void afterThrowing(JoinPoint joinPoint, Exception e){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " occurs excetion:" + e);

}

//环绕通知

//需要携带ProceedingJoinPoint这个类型的参数

//环绕通知类似动态代理的全类名:ProceedingJoinPoint可以绝对是否执行目标方法

//必须要有返回值,返回值即为目标方法的返回值

// @Around("execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))")

// public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint){

// System.out.println("@Around");

// //返回值

// Object result = null;

// //前置通知

// String methodName = proceedingJoinPoint.getSignature().getName();

// try {

// //前置通知

// System.out.println("The methodName:" + methodName + " _The args :" + Arrays.asList(proceedingJoinPoint.getArgs()));

// //执行目标方法

// result = proceedingJoinPoint.proceed();

// //后置通知

// System.out.println("End result:" + result);

// } catch (Throwable e) {

// //e.printStackTrace();

// //异常通知

// System.out.println("Exception:" + e);

// }

// //后置通知

// System.out.println("End...");

// //返回值

// return result;

// }

}

LoggionAspect2.java

切面类2//把这个类升级称为一个切面:返给到IOC容器中---->在声明为一个注解

@Order(1)

@Aspect

@Component

public class LoggionAspect2 {

//定义一个方法用于切点表达式

//一般的该方法不需要填入其他的代码

@Pointcut("execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))")

public void declareJointPointExpression(){ }

@Before("declareJointPointExpression()")

public void beforeMethod1(JoinPoint joinPoint){

System.out.println("--->beforeMethod1");

String methodName = joinPoint.getSignature().getName();

Object [] args = joinPoint.getArgs();

System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));

System.out.println("--->beforeMethod1");

}

/**

* 在方法执行之后执行的代码. 无论该方法是否出现异常

*/

@After("declareJointPointExpression()")

public void afterMethod1(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends");

}

/**

* 在方法法正常结束受执行的代码

* 返回通知是可以访问到方法的返回值的!

*/

@AfterReturning(value="declareJointPointExpression())",

returning="result")

public void afterReturning1(JoinPoint joinPoint, Object result){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends with " + result);

}

/**

* 在目标方法出现异常时会执行的代码.

* 可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码

*/

@AfterThrowing(value="declareJointPointExpression()",throwing="e")

public void afterThrowing1(JoinPoint joinPoint, Exception e){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " occurs excetion:" + e);

}

//环绕通知

//需要携带ProceedingJoinPoint这个类型的参数

//环绕通知类似动态代理的全类名:ProceedingJoinPoint可以绝对是否执行目标方法

//必须要有返回值,返回值即为目标方法的返回值

// @Around("execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))")

// public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint){

// System.out.println("@Around");

// //返回值

// Object result = null;

// //前置通知

// String methodName = proceedingJoinPoint.getSignature().getName();

// try {

// //前置通知

// System.out.println("The methodName:" + methodName + " _The args :" + Arrays.asList(proceedingJoinPoint.getArgs()));

// //执行目标方法

// result = proceedingJoinPoint.proceed();

// //后置通知

// System.out.println("End result:" + result);

// } catch (Throwable e) {

// //e.printStackTrace();

// //异常通知

// System.out.println("Exception:" + e);

// }

// //后置通知

// System.out.println("End...");

// //返回值

// return result;

// }

}

applicationContext.xml

<!-- 配置自动扫描的包 -->

<context:component-scan base-package="com.MrChengsc.AOP"></context:component-scan>

<!-- 前置通知,使切面里的注解起作用 -->

<!-- 使AspectJ注解起作用:自动为匹配的类生成代理效果 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

main:

public static void main(String[] args) {

// AtithmeticCalculator atithmeticCalculator = null;

// atithmeticCalculator = new AtithmeticCalculatorImp();

//

// atithmeticCalculator.add(1, 3);

// System.out.println("---");

// atithmeticCalculator.sub(3, 1);

// System.out.println("---");

// atithmeticCalculator.mul(1, 3);

// System.out.println("---");

// atithmeticCalculator.div(10, 2);

// System.out.println("---");

ApplicationContext ctx = new

ClassPathXmlApplicationContext("AOPContext.xml");

//强制的类型使用接口的类型

AtithmeticCalculator atithmeticCalculator = (AtithmeticCalculator) ctx.getBean(AtithmeticCalculator.class);

int res = atithmeticCalculator.add(3, 6);

System.out.println("res:" + res);

System.out.println("-----");

// int res1 = atithmeticCalculator.mul(2, 3);

// System.out.println("res1:" + res1);

//异常代码的测试

// int res2 = atithmeticCalculator.div(10, 0);

// System.out.println("res2:" + res2);

}

执行的顺序以及结果:

--->beforeMethod1

The method add begins with [3, 6]

--->beforeMethod1

The method add begins with [3, 6]

The method add ends

The method add ends with 9

The method add ends

The method add ends with 9

res:9

-----

注:

1.首先需要在xml文件中进行包的扫描context:component-scan

2.使切面的注解起作用:aop:aspectj-autoproxy</aop:aspectj-autoproxy>

3.使用@Component在要进行处理的类、切面类上

4.使用@Aspect进行标注切面类

5.使用 @Before()在方法上作为前置通知

  1. 使用@After()在方法上作为后置通知,无论该方法是否出现异常

  2. 使用@AfterReturning(value="",returning=""),正常结束后那倒返回值

8.使用 @AfterThrowing(value="",throwing=""),在执行发生异常时,那倒异常信息

9.使用@Around()作为环绕通知,使用比较少

10.使用@Pointcut()放在空方法上,作为切点表达式,引用切点直接使用方法名

11.使用@Order(1)放在类上指定切面的优先级,数值越小优先级越高

12.@After("execution(public * com.MrChengsc.AOP.AtithmeticCalculator.*(..))")

  *:代表所有,任意的

  ..:代表任意的形参

AOP的实现都有这个符号!

Image

本文内容总结:6.spring:AOP(注解)

原文链接:https://www.cnblogs.com/Mrchengs/p/10093490.html

以上是 6.spring:AOP(注解) 的全部内容, 来源链接: utcz.com/z/296953.html

回到顶部