美文网首页
Spring Aop(一)

Spring Aop(一)

作者: 大炮对着虫子 | 来源:发表于2017-10-13 19:16 被阅读9次

AOP:aspect oriented program,面向切面编程
主要应用:打印日志、事务管理、权限控制、访问控制;实现通用的功能,目的是简化代码,方便维护。将主业务逻辑和非业务逻辑分离出来。

下面我们用简单的例子来 阐述 AOP的打印日志功能。

1、导jar
修改pom.xml,导入jar包

 <properties>
    <jdk.version>1.7</jdk.version>
    <charset>utf-8</charset>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>4.1.0.RELEASE</spring.version> 
  </properties>


<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
   <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.14</version>
    </dependency>

导入log4j用以打印日志用。

2、修改spring配置文件的头信息

<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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop.xsd
       ">

3、定义切点程序

切点程序,必须是bean组件的方法。

public class Target {
    //必须是spring组件中的方法
    public String save(String name)
    {
        System.out.println("目标程序执行成功,目标程序的参数为"+name);
        return "嘿嘿";
    }
}

4、定义切面程序

切面程序定义的规则

  • 1、bean组件中的方法
  • 2、返回类型是void
  • 3、参数类型与通知类型相关

5、配置通知类型

前置通知:切面程序在切入点程序执行之前执行
定义切面程序:返回值类型为void 参数类型为JoinPoint 必须是bean组件中的方法
定义切入点程序:必须bean组件中的方法 返回值类型与参数类型不限
通知类型:指定切面程序作用在切入点程序的具体位置

后置通知:切面程序在切入点程序成功执行并返回参数之后执行
定义切面程序:返回值类型为void 参数类型为JoinPoint,Object 必须是bean组件

异常通知:切面程序在切入点程序执行抛出异常之后执行
定义切面程序:返回值类型为void 参数类型为JoinPoint,Throwable 必须是bean组件

最终通知:不管目标程序是否执行成功均会执行
定义切面程序:返回值类型为void 参数类型为JoinPoint 必须是bean组件

//切面程序
public class BeforeAspect {
//前置通知
public void doBefore(JoinPoint jp)
{
    
    Logger logger=Logger.getLogger("BeforeAspect.class");
    //获取目标函数的参数
    logger.info(jp.getArgs()[0]);
    //获取目标函数的反射对象
    logger.info(jp.getSignature());
    //获取目标对象
    logger.info(jp.getTarget().getClass().getName());
    logger.info("程序执行成功");
    
    }
//后置通知
public void doAfterReturning(JoinPoint jp,Object ret)
{
    System.out.println("目标函数的返回值"+ret);
    System.out.println("执行中后置通知");
    }
//异常通知
public void doAfterThrowing(JoinPoint jp,Throwable e)
{
    System.out.println(e.getMessage());
    
    }

//环绕通知
public void doAround(ProceedingJoinPoint pjp) {
//  System.out.println("环绕前置");
    Logger logger = Logger.getLogger("TargetAfterReturn.class");
    double time = System.currentTimeMillis();
    try {
        Object ret = pjp.proceed();
//      System.out.println("返回值:"+ret);
//      System.out.println("环绕后置");
        Thread.sleep(3000);
        double runTime = (System.currentTimeMillis()-time)/1000;
//      System.out.println(pjp.getSignature()+"的执行时间:"+runTime+"s");
        logger.info(pjp.getSignature()+"的执行时间:"+runTime+"s");
    } catch (Throwable e) {
        // TODO Auto-generated catch block
        System.out.println(e.getMessage());
//      System.out.println("环绕异常");
    }finally {
//      System.out.println("环绕最终");
    }
}
}

下面通过配置文件,将切面程序和切点联系起来

<bean id="target" class="target.Target">
</bean>
<bean id="beforeAspect" class="aspect.BeforeAspect">
</bean>


<aop:config>

<aop:pointcut expression="execution(* target.Target.save(String))" id="targetPoint" /> 

 <aop:aspect ref="beforeAspect">
 <!-- 配置通知类型,指定为前置通知;Mehtod 为切面程序的方法名,pointcut -->
 <aop:before method="doBefore" pointcut-ref="targetPoint"/>
 <aop:after-returning method="doAfterReturning" pointcut-ref="targetPoint" returning="ret"/>
 <aop:after-throwing method="doAfterThrowing"  pointcut-ref="targetPoint" throwing="e"/>
            <aop:around method="doAround" pointcut-ref="targetPoint"/>
        
 </aop:aspect>
</aop:config>
AOP注解

1、开启自动代理,开启自动扫描。

<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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop.xsd
      http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd
       ">
<context:component-scan base-package="aspect,target"></context:component-scan>
      
      <!-- 开启自动代理模式 -->
      <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

2、将切入点程序与切面程序声明为bean组件

3、使用注解:

@Component(value="beforeAspect")
@Aspect
public class BeforeAspect {
    
    @Before(value="within(target.Target)")
public void doBefore(JoinPoint jp)
{
    
    Logger logger=Logger.getLogger("BeforeAspect.class");
    //获取目标函数的参数
    logger.info(jp.getArgs()[0]);
    //获取目标函数的反射对象
    logger.info(jp.getSignature());
    //获取目标对象
    logger.info(jp.getTarget().getClass().getName());
    logger.info("程序执行成功");
    
    }
@AfterReturning(pointcut="within(target.Target)",returning="ret")
public void doAfterReturning(JoinPoint jp,Object ret)
{
    System.out.println("目标函数的返回值"+ret);
    System.out.println("执行中后置通知");
    }
@AfterThrowing(pointcut="within(target.Target)",throwing ="e")
public void doAfterThrowing(JoinPoint jp,Throwable e)
{
    System.out.println(e.getMessage());
    
    }
}

相关文章

网友评论

      本文标题:Spring Aop(一)

      本文链接:https://www.haomeiwen.com/subject/fqmzyxtx.html