java中AOP的理解和使用

java中AOP的理解和使用

  • 1.什么是AOP?
  • 2.AOP的作用(特点)是什么?
  • 3.AOP的注解
    • 1.Target
    • 2.Retention
    • 3.Document
    • 4.Inherited
    • 5.Aspect
    • 6.Pointcut
  • 4.通知形式
  • 5.代码使用
    • 1.定义主体类
    • 2.设置切面
    • 3.使用AOP注解

1.什么是AOP?

AOP就是面向切面编程,或者叫面向方面编程,或者开玩笑的说叫面向方便面编程,如果粗俗的理解,就是可以自定义注解,然后通过自己定义的方式定义注解的作用。

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

2.AOP的作用(特点)是什么?

AOP代表的是一个横向的关 系,将“对象”比作一个空心的圆柱体,其中封装的是对象的属性和行为;则面向方面编程的方法,就是将这个圆柱体以切面形式剖开,选择性的提供业务逻辑。而 剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹,但完成了效果。

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

3.AOP的注解

1.Target

@Target 注解的作用目标

	(1)@Target(ElementType.TYPE) —— 接口、类、枚举、注解
	(2)@Target(ElementType.FIELD) —— 字段、枚举的常量
	(3)@Target(ElementType.METHOD) —— 方法
	(4)@Target(ElementType.PARAMETER) —— 方法参数
	(5)@Target(ElementType.CONSTRUCTOR) —— 构造函数
    (6)@Target(ElementType.LOCAL_VARIABLE) —— 局部变量
	(7)@Target(ElementType.ANNOTATION_TYPE) —— 注解
	(8)@Target(ElementType.PACKAGE) —— 包

2.Retention

@Retention 注解的保留位置

(1) RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含。
(2)RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得。
(3)RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。

3.Document

说明该注解将被包含在javadoc中

4.Inherited

说明子类可以继承父类中的该注解

5.Aspect

作用是把当前类标识为一个切面供容器读取

6.Pointcut

Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码

4.通知形式

 (1) 前置通知(@Before):在目标方法调用之前调用通知
 (2) 后置通知(@After):在目标方法完成之后调用通知
 (3) 环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法
 (4) 返回通知(@AfterReturning):在目标方法成功执行之后调用通知
 (5) 异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知

5.代码使用

1.定义主体类

java中AOP的理解和使用_第1张图片

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
/**
 * @Documented 是元注解,可以修饰其他注解。许多注解头部都有@Documented注解
 * 例如jdk中自带的@Deprecated注解(路径是:java/lang/Deprecated.java)头部就含有这个注解
 *
 * 在自定义注解的时候可以使用@Documented来进行标注,如果使用@Documented标注了,在生成javadoc的时候就会把@Documented注解给显示出来。
 */
@Documented
public @interface ClhTestAOP {
	String chen() default "1";
	String liang() default "1";
	String hong() default "1";
}

2.设置切面

java中AOP的理解和使用_第2张图片
java中AOP的理解和使用_第3张图片



@Slf4j
@Aspect
@Component
public class ClhTestAOPAspect {


	private String chen = "";
	private String liang = "";
	private String hong = "";


	/**
	 * 切点
	 */
	@Pointcut(value = "@annotation(annotation.ClhTestAOP)")
	public void logPointCut() {

	}


	/**
	 * 前置通知(@Before):在目标方法调用之前调用通知
	 * 后置通知(@After):在目标方法完成之后调用通知
	 * 环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法
	 * 返回通知(@AfterReturning):在目标方法成功执行之后调用通知
	 * 异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知
	 * @param joinPoint
	 * @return
	 */
	@Before(value = "logPointCut()")
	public void doBefore(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		ClhTestAOP clhTestAOP = method.getAnnotation(ClhTestAOP.class);
		if (clhTestAOP != null) {
			chen = clhTestAOP.chen();
			liang = clhTestAOP.liang();
			hong = clhTestAOP.hong();
		}

		if(chen.equals("1")) {
			log.info("@Before ================== chen 1 ");
		}else {
			log.info("@Before ================== chen default ");
		}

		if(liang.equals("1")) {
			log.info("@Before ================== liang 1 ");
		}else {
			log.info("@Before ================== liang default ");
		}

		if(hong.equals("1")) {
			log.info("@Before ================== hong 1 ");
		}else {
			log.info("@Before ================== hong default ");
		}

	}

	@After(value = "logPointCut()")
	public void doAfter(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		ClhTestAOP clhTestAOP = method.getAnnotation(ClhTestAOP.class);
		if (clhTestAOP != null) {
			chen = clhTestAOP.chen();
			liang = clhTestAOP.liang();
			hong = clhTestAOP.hong();
		}

		if(chen.equals("1")) {
			log.info("@After ================== chen 1 ");
		}else {
			log.info("@After ================== chen default ");
		}

		if(liang.equals("1")) {
			log.info("@After ================== liang 1 ");
		}else {
			log.info("@After ================== liang default ");
		}

		if(hong.equals("1")) {
			log.info("@After ================== hong 1 ");
		}else {
			log.info("@After ================== hong default ");
		}

	}

	@Around(value = "logPointCut()")
	public void doAround(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		ClhTestAOP clhTestAOP = method.getAnnotation(ClhTestAOP.class);
		if (clhTestAOP != null) {
			chen = clhTestAOP.chen();
			liang = clhTestAOP.liang();
			hong = clhTestAOP.hong();
		}

		if(chen.equals("1")) {
			log.info("@Around ================== chen 1 ");
		}else {
			log.info("@Around ================== chen default ");
		}

		if(liang.equals("1")) {
			log.info("@Around ================== liang 1 ");
		}else {
			log.info("@Around ================== liang default ");
		}

		if(hong.equals("1")) {
			log.info("@Around ================== hong 1 ");
		}else {
			log.info("@Around ================== hong default ");
		}

	}

	@AfterReturning(value = "logPointCut()")
	public void doAfterReturning(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		ClhTestAOP clhTestAOP = method.getAnnotation(ClhTestAOP.class);
		if (clhTestAOP != null) {
			chen = clhTestAOP.chen();
			liang = clhTestAOP.liang();
			hong = clhTestAOP.hong();
		}

		if(chen.equals("1")) {
			log.info("@AfterReturning ================== chen 1 ");
		}else {
			log.info("@AfterReturning ================== chen default ");
		}

		if(liang.equals("1")) {
			log.info("@AfterReturning ================== liang 1 ");
		}else {
			log.info("@AfterReturning ================== liang default ");
		}

		if(hong.equals("1")) {
			log.info("@AfterReturning ================== hong 1 ");
		}else {
			log.info("@AfterReturning ================== hong default ");
		}

	}

	@AfterThrowing(value = "logPointCut()")
	public void doAfterThrowing(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		ClhTestAOP clhTestAOP = method.getAnnotation(ClhTestAOP.class);
		if (clhTestAOP != null) {
			chen = clhTestAOP.chen();
			liang = clhTestAOP.liang();
			hong = clhTestAOP.hong();
		}

		if(chen.equals("1")) {
			log.info("@AfterThrowing ================== chen 1 ");
		}else {
			log.info("@AfterThrowing ================== chen default ");
		}

		if(liang.equals("1")) {
			log.info("@AfterThrowing ================== liang 1 ");
		}else {
			log.info("@AfterThrowing ================== liang default ");
		}

		if(hong.equals("1")) {
			log.info("@AfterThrowing ================== hong 1 ");
		}else {
			log.info("@AfterThrowing ================== hong default ");
		}

	}

}

3.使用AOP注解

java中AOP的理解和使用_第4张图片

	@ClhTestAOP(chen = "chen", liang = "liang", hong = "hong")
	public void test() {
		System.out.println("测试AOP··········");
	}

你可能感兴趣的:(java,jvm,面试,springcloud,spring,boot)