spring学习--面向切面编程AOP和AspectJ

来源:互联网 发布:淘宝店铺首页大图尺寸 编辑:程序博客网 时间:2024/05/16 02:18

—AOP(面向切面编程)

1.代理模式

代理模式是指,为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用.作用是增强功能和控制访问.分为:静态代理:在程序运行之前已经定义好代理类,代理类和目标类要实现相同的接口动态代理:在程序运行时才确定代理类和目标类的关系,又分为    a.JDK动态代理,要求目标对象必须实现接口    b.CGLIB动态代理,要求目标类必须能够被继承,即不是final类.它的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理类

2.AOP简介

AOP,即面向切面编程,是OOP的补充.利用AOP可以让业务逻辑和业务逻辑方法解耦合,提高了代码的可用性,大大提高了开发效率.底层采用JDK和CGLIB动态代理实现的.

3.什么是AspectJ

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。

4.基于Annotation的五种通知

a.@Before前置通知

package com.aspectj.demo1;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.Signature;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import com.aspectj.common.LoggerUtil;@Aspect// 定义切面类,就是对业务方法进行增强public class MyAspect {    // 前置通知    // 在目标方法执行前执行前置通知    @Before(value="execution(public * com.aspectj.demo1.SomeServiceImpl.run(..))")    public void beforeExcute(JoinPoint point) throws Exception{        System.out.println("前置通知被执行");        // 得到切入点表达式        // execution(void com.aspectj.demo1.SomeService.run())        LoggerUtil.doLog(point);        // 得到方法签名        // void com.aspectj.demo1.SomeService.run()        LoggerUtil.doLog(point.getSignature());        // 得到目标对象        // com.aspectj.demo1.SomeServiceImpl@4b5a5ed1        LoggerUtil.doLog(point.getTarget());        // 得到方法名字        // run        Signature signature = point.getSignature();        String name = signature.getName();        LoggerUtil.doLog(name);    }}

b.@AfterReturning后置通知

package com.aspectj.demo2;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.Aspect;@Aspect// 定义切面类,就是对业务方法进行增强public class MyAspect {    // 后置通知    // 因为是在业务方法结束后执行,所以有返回值    // 但是增强后的值不会改变原来业务方法的返回值    @AfterReturning(value="execution(* *..SomeServiceImpl.*(..))",returning="result")    // result表示的是业务方法的返回值    public void afterReturningExecute(JoinPoint point ,Object result){        // 获取方法的名字        String name = point.getSignature().getName();        if("getName".equals(name)){            result += " end";        }        System.out.println("后置通知增强后的返回值:" + result);    }}

c.@Around环绕通知

package com.aspectj.demo3;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;@Aspect@Component// 定义切面类,就是对业务方法进行增强public class MyAspect {    // 环绕通知    // 在目标方法执行前后都执行    // 必须有返回值    // 可以改变原目标方法的返回值    @Around(value="execution(* *..SomeServiceImpl.getName(..))")    public Object aroundExecute(ProceedingJoinPoint point) throws Throwable{        // 得到目标方法的返回值        String result = (String) point.proceed();        result += " my";        System.out.println("环绕通知的返回值:" + result);        return result;    }}

d.@AfterThrowing异常通知

package com.aspectj.demo4;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;import com.aspectj.common.LoggerUtil;@Aspect@Component// 定义切面类,就是对业务方法进行增强public class MyAspect {    // 异常通知    @AfterThrowing(value="execution(* *..SomeServiceImpl.run(..))",throwing="e")    public void afterThrowingExecute(Throwable e) throws Exception{        System.out.println("程序发生异常");        LoggerUtil.doLog(e);    }}

e.@After最终通知

package com.aspectj.demo5;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;@Aspect@Component// 定义切面类,就是对业务方法进行增强public class MyAspect {    // 最终通知    // 无论目标对象是否抛出异常,该增强都会被执行    @After(value="execution(* *..SomeServiceImpl.run(..))")    public void afterExecute(){        System.out.println("程序发生异常");    }}

f.xml文件

<context:component-scan base-package="com.aspectj.demo5"/><!-- 注册自动代理生成器 --><aop:aspectj-autoproxy />

5.基于XML的五种通知

只列举一个,其他都类似

<bean id="someService" class="com.aspectj.demo5.SomeServiceImpl"/><bean id="myAspect" class="com.aspectj.demo5.MyAspect"/><aop:config>     <aop:pointcut expression="execution(* *..SomeServiceImpl.run(..))" id="afterPointCut"/>     <aop:aspect ref="myAspect">        <aop:after method="afterExecute" pointcut-ref="afterPointCut"/>     </aop:aspect> </aop:config>
原创粉丝点击