Spring 学习二-----AOP的原理与简单实践

1、Spring  AOP的原理

AOP全名Aspect-Oriented Programming,中文直译为面向切面(方面)编程。何为切面,就好比说咱们系统中的权限管理,日志,事务等咱们均可以将其当作一个个切面。html

Spring AOP 采用的是动态代理的设计模式来实现切面编程的。spring

首先,咱们能够经过 express

23种设计模式----------代理模式(三) 之 动态代理模式编程

来了解下动态代理模式,再次再也不赘述。设计模式

咱们来看看Spring AOP 是怎样运用动态代理模式的。在Spring AOP 经过安全

调用流程以下:
一、实现InvocationHandler接口
二、经过ProxyFactoryBean用于建立代理类(根据Advisor生成的Bean,也就是TargetBean的代理)
三、调用invoke方法 
而后,AOP中几个重要的概念是:
 一、关注点(concern)
   一个关注点能够是一个特定的问题,概念、或者应用程序的兴趣点。总而言之,应用程序必须达到一个目标
   安全验证、日志记录、事务管理都是一个关注点
   在oo应用程序中,关注点可能已经被代码模块化了还可能散落在整个对象模型中
二、横切关注点(crosscutting concern)
   如何一个关注点的实现代码散落在多个类中或方法中
三、方面(aspect)
   一个方面是对一个横切关注点模块化,它将那些本来散落在各处的,
   用于实现这个关注点的代码规整在一处,能够经过@Aspect标注或在applictionContext.xml中进行配置: 
      <aop:aspect id="fourAdviceAspect" ref="fourAdviceBean" order="2"> 
四、建议(advice)通知
   advice是point cut执行代码,是方面执行的具体实现,如
 <aop:aspect ref="advices">
            <!--切点-->
            <aop:pointcut id="pointcut1" expression="execution(* com.jay.springAOP.aop01.Math.*(..))"/>
            <!--链接通知方法与切点-->
            <aop:before method="before" pointcut-ref="pointcut1"/>
            <aop:after method="after" pointcut-ref="pointcut1"/>
        </aop:aspect>
五、切入点(pointcut)
   用于指定某个建议用到何处
<aop:pointcut id="myPointcut" expression="execution(* com.wicresoft.app.service.impl.*.*(..))" method="release" /> 
六、织入(weaving)
   将aspect(方面)运用到目标对象的过程
七、链接点(join point)
  程序执行过程当中的一个点 

 通知类型app

try{
//前置通知
//环绕通知
//调用目标对象方法
//环绕通知
//后置通知
}catch(){
//异常通知
}finally{
//终止通知
}模块化

 

 

注:图片来源于:http://blog.csdn.net/lirui0822/article/details/8555691 post

关于PointCut中使用的execution的说明:性能

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?) 

modifiers-pattern:方法的操做权限

ret-type-pattern:返回值

declaring-type-pattern:方法所在的包

name-pattern:方法名

parm-pattern:参数名

throws-pattern:异常

记忆法则就是Java定义一个方法时的样子:public boolean produceValue(int oo) throws Exception, 只要在方法名前加上包名就能够了。

其中,除ret-type-pattern和name-pattern以外,其余都是可选的。上例中,execution(* com.spring.service.*.*(..))表示com.spring.service包下,返回值为任意类型;方法名任意;参数不做限制的全部方法。

2、Spring AOP的简单实践

一、首先定义一个日志切面,采用前置通知

package com.jay.springAOP.aopDecorator;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
* 一个用于记录日志的切面
* Created by xiang.wei on 2017/8/14.
*/
@Component
@Aspect
public class LoggerAdvices {

@Before("execution(* com.jay.springAOP.aopDecorator.*.*(..))")
public void addLogger(JoinPoint joinPoint) {
System.out.println(joinPoint.getSignature().getName());
Logger logger= LoggerFactory.getLogger(this.getClass());
//记录日志
logger.debug("-------起始操做----------");
logger.debug("-------结束操做-----------");
}
}

二、定义一个用于性能统计的切面,其中定义了一个环绕通知

package com.jay.springAOP.aopDecorator;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 一个用于性能的统计
 * Created by xiang.wei on 2017/8/14.
 */
@Component
@Aspect
public class PerformanceAdvices {

    @Around("execution(* com.jay.springAOP.aopDecorator.*.*(..))")
    public Object execute(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println(pjp.getSignature().getName());
        System.out.println("开始时间:"+System.currentTimeMillis());
        Object result = pjp.proceed();
        System.out.println("结束时间:"+System.currentTimeMillis());
        return result;
    }
}

三、相关的业务代码

package com.jay.springAOP.aopDecorator;

import org.springframework.stereotype.Service;

/**
 * Created by xiang.wei on 2017/8/14.
 */
@Service("paymentCommand")
public class PaymentCommand {


    public void pay() {
        //执行下订单操做
        int j=0;
        for (int i=0;i<10000;i++ ) {
            j++;
        }
        //执行支付操做
        System.out.println("进行支付");
    }
}
package com.jay.springAOP.aopDecorator;

import org.springframework.stereotype.Service;

/**
 * Created by xiang.wei on 2017/8/14.
 */
@Service("placeOrderCommand")
public class PlaceOrderCommand{

    public void handleOrder() {
        //执行下订单操做
        int j=0;
        for (int i=0;i<100000;i++ ) {
            j++;
        }
        System.out.println("进行下单操做");
    }
}

四、测试类:

package com.jay.springAOP.aopDecorator;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by xiang.wei on 2017/8/15.
 */
public class Client {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("aopDecorator.xml");

        PlaceOrderCommand placeOrderCommand = ctx.getBean("placeOrderCommand", PlaceOrderCommand.class);
        placeOrderCommand.handleOrder();

        PaymentCommand paymentCommand = ctx.getBean("paymentCommand",PaymentCommand.class);
        paymentCommand.pay();
    }
}

测试结果以下:

相关文章
相关标签/搜索