spring回顾系列:AOP

来源:互联网 发布:固态优化win10 编辑:程序博客网 时间:2024/04/27 16:20

   AOP面向切面编程,它的出现是为了解耦。AOP可以让一组类共享相同的行为。在OOP面向对象编程中只能通过继承和实现接口方式来达到这一目的,但是无论是使用继承还是实现接口都会使代码的耦合度增强。

   spring支持AspectJ的注解式切面编程:

  1. 使用@Aspect声明一个切面。

  2. 使用@After、@Before、@Around定义建言,可以直接将切点作为参数。

  3. 使用@PointCut定义切点,使得切点复用。

  4. 符合条件的被拦截处称为连接点(JoinPoint)

  • 作用面

@Servicepublic class TestAOP{    public int add(int n1,int n2){        int res=n1+n2;        System.out.println(n1+"+"+n2+"="+res);        return res;    }        public int mul(int n1,int n2){        int res=n1*n2;        System.out.println(n1+"*"+n2+"="+res);        return res;    }}

   这个service类是用来承受切面的作用面。

  • 切面

@Component@Aspectpublic class Advices {// 定义切点@Pointcut("execution(* com.TestAOP.*(..))")public void pointcut() {}// 前置通知@Before("pointcut()")public void before(JoinPoint jp) {// 得到作用于方法上的方法名System.out.println(jp.getSignature().getName());System.out.println("----------前置通知----------");}// 最终通知@After("pointcut()")public void after(JoinPoint jp) {System.out.println("----------最终通知----------");}// 环绕通知@Around("execution(* com.TestAOP.a*(..))") // 只作用与a开头的方法上public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println(pjp.getSignature().getName());System.out.println("----------环绕前置----------");Object result = pjp.proceed();System.out.println("----------环绕后置----------");return result;}// 返回结果通知@AfterReturning(pointcut = "pointcut()", returning = "result")public void afterReturning(JoinPoint jp, Object result) {System.out.println(jp.getSignature().getName());System.out.println("结果是:" + result);System.out.println("----------返回结果----------");}// 异常后通知@AfterThrowing(pointcut = "pointcut()", throwing = "exp")public void afterThrowing(JoinPoint jp, Exception exp) {System.out.println(jp.getSignature().getName());System.out.println("异常消息:" + exp.getMessage());System.out.println("----------异常通知----------");}}

@Pointcut("execution(*com.TestAOP.*(..))")是用于定义一个切点,能够实现复用。

  • xml形式对比

    <!-- 通知 -->    <bean id="advices" class="com.TestAOP"></bean>        <!-- aop配置 -->    <aop:config proxy-target-class="true">        <!--切面 -->        <aop:aspect ref="advices">            <!-- 切点 -->            <aop:pointcut expression="execution(* com.TestAOP.*(..))" id="point"/>            <!--连接通知方法与切点 -->            <aop:before method="before" pointcut-ref="point"/>            <aop:after method="after" pointcut-ref="point"/>        </aop:aspect>    </aop:config>

以上的xml形式的代码,就相当于之前使用java代码+注解形式的切面定义和切面方法的编写。

  • 配置和运行

@Configuration@ComponentScan("com.test")@EnableAspectJAutoProxypublic class Config {}

@Testpublic void run2() {AnnotationConfigApplicationContext cc = new AnnotationConfigApplicationContext(Config.class);Math math = cc.getBean(Math.class);math.add(10, 20);math.mul(1, 2);}
注:使用@EnableAspectJAutoProxy注解开启spring对AspectJ代理的支持