Spring-Aop模块

文章目录

Aop作用

  面向切面编程,以无侵入的方式,使一组类共享相同的行为。

  • 相关术语:
    • Aspect切面: 多个位置的同一功能,每个切面都侧重于一个特定的横切功能。
      • Joinpoint连接点: 横切功能的执行点
        • Advice通知: 横切面执行的具体功能,前置、后置、环绕、异常、最终通知
        • Pointcut切点: 用以匹配连接点的正则表达式。每当任何连接点匹配一个切入点时,就执行该切入点相关联的指定通知。
        • Weaving织入: 链接切面和目标对象来创建一个通知对象的过程。

JDK动态代理: Spring AOP的首选方法,在Spring中的对象实现某一接口,就会使用JDK动态代理。利用反射机制生成一个实现代理接口的匿名类。

CGLIB代理: 当对象没有实现接口时,使用此动态代理方式。将对象的class文件加载进来,修改其字节码生成子类,相当于继承。

  • 在Spring中,使用Aspect注解
    @Aspect
    @Component
    class LogAspect{
    	1.within表达式匹配包类型
    		//匹配类中所有的方法
    	@Pointcut("within(com.zp.ProductServiceImpl)")
    	public void matchClass(){}
    		//匹配包中所有类的全部方法
    	@Pointcut("within(com.zp.daoPackage..)")
    	public void matchPackage(){}
    	2.this、target、bean表达式匹配对象类型
    		//匹配以 AOP对象的目标对象 为 指定类型 的方法
    		//如ShopServiceImpl的
    	@Pointcut("this(com.zp.ShopServiceImpl)")
    	public void matchThis(){}
    		//匹配实现该接口的目标对象
    	@Pointcut("target(com.zp.ShopService)")
    	public void matchTarget(){}
    		//匹配所有以Service结尾的bean的全部方法
    	@Pointcut("bean(*Service)")
    	public void matchBean(){}
    	3.使用args表达式匹配参数,用于获取方法中的参数。
    		//匹配第一个参数为Long类型的方法,将
    	@Pointcut("args(Long,*)")
    	public void matchArgs(){}
    	4.使用匹配注解
    		//匹配注解了@test的方法
    	@Pointcut("@annotation(com.zp.annotation.test)")
    	public void matchAnno(){}
    		//匹配注解了@test的类的所有方法,要求级别为CLASS
    	@Pointcut("@within(com.zp.annotation.test)")
    	public void matchAnnoWithin(){}
    		//匹配注解了@test的类下的所有方法,要求级别为RUNTIME
    	@Pointcut("@target(com.zp.annotation.test)")
    	public void matchAnnoTarget(){};
    		//匹配传入的参数 注解了@test 的方法
    	@Pointcut("@args(com.zp.annotation.test)")
    	public void matchAnnoArgs(){}
    	5.使用Execution表达式
    		//execution(modifier-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
    		//modifier-pattern 访问修饰符	可省
    		//ret-type-pattern 返回值类型 *所有类型、全路径类名、普通类型 不可省
    		//declaring-type-pattern  类路径 可省
    		//name-pattern 方法名 *所有方法、set*或*set模糊匹配 不可省
    		//param-pattern 参数类型 具体类型,多个类型用“,“隔开;*一个任意类型参数;..表示0个或多个任意类型参数。不可省
    		//throws-pattern 异常类型匹配 可省
    	@Pointcut("execution(public * com.zp.ShopServiceImpl *(String,*) *)")
    	public void matchExecution(){}
    
    	通知Advice
    	//@After 切点正常运行结束后执行,若切点抛出异常,则在抛出异常前执行。
    	//@AfterThrowing 切点抛出异常后,执行。
    	//@AfterReturning 切点正常结束后执行,若切点异常则不执行。
    	//@Around 可以在切入点执行前后自定义一些操作。环绕通知需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。在执行ProceedingJoinPoint对象的proceed方法前相当于Before前置通知;执行proceed方法相当于运行切入点(同时可以获取参数);在方法执行之后相当于After后置通知,如果运行切入点抛出异常,则catch中的内容相当于AfterThrowing异常通知;finally中的内容无论切入点是否抛出异常,都将执行
    	//@Before 运行前执行
    	@Before("matchExecution()")
    	public void doBefore(JoinPoint jp){
    		....
    	}
    	@Around("matchAll()")
    	public Object around(ProceedingJoinPoint joinPoint) {
        	Object result = null;
        	authService.checkAccess();
        	System.out.println("befor 在切入点执行前运行");
        	try{
            	result = joinPoint.proceed(joinPoint.getArgs());//获取参数
            	System.out.println("after 在切入点执行后运行,result = " + result);
        	} catch (Throwable e) {
            	System.out.println("after 在切入点执行后抛出exception运行");
            	e.printStackTrace();
        	} finally {
            	System.out.println("finally......");
        	}
       		return result;
    	}
    		
    }
    
  • XML配置方式
	//JoinPoint连接对象
	class AopAspect{
		public void doBefore(JoinPoint jp){
			System.out.println("前置通知");
		}	
		public void doAfterReturning(JoinPoint jp,String result){
			System.out.println("执行后,后置通知");
		}
		public void doAfterThrowing(JoinPoint jp,Excetion ex){
			System.out.println("产生异常后执行");	
		}
		public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
			System.out.println("前置通知");
			//调用proceed()执行切入点方法执行
			Object result = pjp.proceed();
			System.out.println("后置通知");
			return result;	
		}
		public void doAfter(JoinPoint jp){
			System.out.println("最终通知");	
		}
	}
<beans>
	<bean id="aopAspect" class="AopAspect" />
	<aop:config>
		<aop:aspect ref="aopAspect">
			<aop:pointcut id="pointcut" expression="execution(public * com.zp.ShopService.. *(..))" />
			<aop:before method="doBefore" pointcut-ref="pointcut" />
			<aop:after method="doAfter" pointcut-ref="pointcut" />
			<aop:after-returning method="doAfterReturning" pointcut-ref="point-cut" return="result" />
			<aop:after-throwing method="doAfterThrowing" pointcut-ref="pointcut"
	throwing="ex" />
			<aop:around method="doAround" pointcut-ref="pointcut" />
		</aop:aspect>
	</aop:config>
</beans>
  • JoinPoint:包装了切面方法的相关信息。
interface JoinPoint{
	//完成Method和Advice的执行
	Object proceed() throws Throwable;
	//获取代理的对象
	Object getThis();
	//获取代理的静态部分(代理的方法)
	AccessibleObject getStaticPart();
}
  • Spring AOP与AspectJ
      Spring AOP是AOP的简单实现,只能在Spring框架中使用。AspectJ是完整的AOP实现方式且有自己的织入编译器。
      Spring Aop可以使用AspectJ的注解功能,但实质上的底层的实现是Spring Aop。
    • Spring AOP织入方式:运行时织入,故此效率低。JDK动态代理时需要实现特定的接口;CGLIB代理时,不能织入使用final与static修饰的类和方法。
    • AspectJ织入方式:编译时织入,AspectJ编译器同时加载切面代码和源程序生成一个织入后的文件输出;编译后织入,即二进制织入,用以编织现有的类文件和JAR文件与切面;加载时织入,与二进制织入一样,不同的是织入延后,直到类加载器加载到JVM。
        故此,AaspectJ比Spring Aop快的多
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值