• 【spring 5】AOP:spring中对于AOP的的实现


    在前两篇博客中,介绍了AOP实现的基础:静态代理和动态代理,这篇博客介绍spring中AOP的实现。

    一、采用Annotation方式

    首先引入jar包:aspectjrt.jar && aspectweaver.jar

    applicationContext配置文件:

    <span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	     xmlns:aop="http://www.springframework.org/schema/aop"
    	     xmlns:tx="http://www.springframework.org/schema/tx"
    	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
               
        <!-- 启用AspectJ对Annotation的支持 -->       
    	<span style="color:#ff0000;"><aop:aspectj-autoproxy/></span>           
    	
    	<bean id="user" class="com.angel.spring.User"/>
    	
    	<bean id="successfulHandler" class="com.angel.spring.SuccessfulHandler"/>
    	
    </beans>
    </span>
    接口和实现类省略


    代理拦截类:

    <span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.spring;
    
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class SuccessfulHandler {
    	
    	
    	/**
    	 * 定义Pointcut,Pointcut的名称为addAddMethod(),此方法没有返回值和参数
    	 * 该方法就是一个标识,不进行调用
    	 */
    	@Pointcut("execution(* add*(..))")
    	private void addAddMethod(){};
    	
    	
    	/**
    	 * 定义Advice,表示我们的Advice应用到哪些Pointcut订阅的Joinpoint上
    	 */
    	//@Before("addAddMethod()")
    	@After("addAddMethod()")
    	private void checkSecurity() {
    		System.out.println("-------Angel,方法执行成功!-------");
    	}		
    }
    </span>
    通过以上的配置,就可以实现对于方法调用的拦截。我们使用的注解有@Aspect,标记此类是一个横切面的插入类(拦截类),然后使用@Pointcut,标记我们的拦截方法需要作用于那些地方,最后使用@Before或者@After标记我们的拦截方法是作用于被调用方法前或者后。

    但是,通过注解的方式,我们就需要为每个方法都添加注解,如果要修改的话,还得逐一修改,这样子,虽然同样轻便,但是如果有一个地方统一配置AOP的话,那就会更为简便,接下来,我们看第二种实现方式:采用配置方式

    二、采用配置方式

    applicationContext的配置:

    <span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
    
    	<!-- 启用AspectJ对Annotation的支持 -->
    	<!-- <aop:aspectj-autoproxy/> -->
    
    	<bean id="user" class="com.angel.spring.User" />
    
    	<bean id="successfulHandler" class="com.angel.spring.SuccessfulHandler" />
    
    	<aop:config>
    		<aop:aspect id="IsSuccessfulAspect" ref="successfulHandler">
    			<!-- com.bjpowernode.spring包下所有的类所有的方法
    			 <aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.*(..))"/> -->
    			<!-- com.bjpowernode.spring包下所有的类的以add和del开头的方法-->
    			<aop:pointcut id="addAddMethod" expression="execution(* com.angel.spring.*.add*(..)) || execution(* com.angel.spring.*.del*(..))" />
    			<aop:before method="checkSecurity" pointcut-ref="addAddMethod" />
    		</aop:aspect>
    	</aop:config>
    
    </beans>
    </span>
    拦截类:

    <span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.spring;
    
    import org.aspectj.lang.JoinPoint;
    
    
    public class SuccessfulHandler {
    	
    	private void checkSecurity(JoinPoint joinPoint) {
    	
    		System.out.println("-------Angel,方法执行成功!-------");
    	}		
    }</span>

    经过这样的配置就可以实现方法的拦截了,但有时候,我们不仅需要拦截方法名称,我们还需要知道,在执行这个方法的时候,用户到底传递了什么样的参数,那么,我们需要在拦截类采用Advice中添加一个JoinPoint参数,取得客户端调用的方法名称及参数值,如:

    <span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.spring;
    
    import org.aspectj.lang.JoinPoint;
    
    
    public class SuccessfulHandler {
    	
    	private void checkSecurity(JoinPoint joinPoint) {
    		for (int i=0; i<joinPoint.getArgs().length; i++) {
    			System.out.println(joinPoint.getArgs()[i]);
    		}
    		System.out.println(joinPoint.getSignature().getName());
    		System.out.println("-------Angel,方法执行成功!-------");
    	}		
    }</span>

    三、采用CGLIB代理

    以上的例子,我们都是采用JDK的代理实现的AOP,JDK的动态代理是代理的接口,如果有些类并没有实现接口,那么我们将不得不采用另外一种代理方式:CGLIB动态代理。如:

    首先,引入支撑CGLIB的jar包cglib-nodep.jar

    其次,在applicationContext配置文件中,强制开启CGLIB代理:

    <span style="font-family:KaiTi_GB2312;font-size:18px;"><!-- 强制使用CGLIB代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true" /></span>

    区别:User类不再实现IUser接口,而是一个单独的类,代理成功!


    四、总结

    JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

    对于AOP的总结,到此结束,接下来总结事务的知识点。PS:深刻感觉,之前对于AOP是被吓退了!



  • 相关阅读:
    Ubuntu 虚拟机空间不足增加空间笔记
    am335x sd卡启动开启识别emmc kernel 上的改动
    Delphi实现树型结构具体实例
    学习 TTreeView [15]
    delphi中Treeview的使用介绍
    按下F2编辑dxDBTreeView的节点
    dbtreeview
    我的dbtreeview–treeview直接连接数据表_delphi教程
    SqlDbx连接oracle(可用)
    SqlDbx连接oracle(无需安装Oracle客户端)
  • 原文地址:https://www.cnblogs.com/hhx626/p/6010307.html
Copyright © 2020-2023  润新知