Spring(五、AOP面向切面编程)

1、面向切面编程(AOP)的概念:把项目中需要在多处用到的功能,比如日志、安全和事物等集中到一个类中处理,而不用在每个需要用到该功能的地方显式调用。
2、术语解释:
横切关注点:分布应用于多处的功能
切面:横切关注点可以被模块化为一个类,这个类被称为一个切面
通知(advice):切面要完成的工作。Spring的通知有5种类型:before、after、after-returning、after-throwing和around这五种类型。
连接点(joinpoint):连接点表示在何种操作发生时应用切面。比如方法调用时、修改字段时和抛出异常时等等
切点(pointcut):一般用某个包中的类的明确的方法来指定在何处应用切面,应用切面的这个点便称为切点,一般用切点来指定连接点。

第一步:导入jar包(Spring与AspectJ)
第二步:Spring的主配置文件:
i.在表头中添加aop、context的命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    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/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

第三歩:在配置文件中开启aop注解

<aop:aspectj-autoproxy proxy-target-class="true"/>

第四步:让类生产bean对象,通过扫描包,所有注解的类都生产bean

<context:component-scan base-package="com.iotek.aspect"/>

第五步: 定义横切面类

package com.iotek.aspect;


import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component("logAspect")
public class LogAspect {
    /*
     * 1、@Before:在某个方法执行前调用
     * 2、@After:在某个方法执行后调用
     * 3、@AfterReturning:在某个方法执行后调用,且获得其返回值
     * 4、@AfterThrowing:在某个方法执行后调用,如果有异常在执行此方法
     * 5、@Around:环绕执行,包含了@Before与@After等(不常用)
     * 
     *  注意:执行参数的设置
     *      例如:@Before("execution(public void com.iotek.daoImpl.ComputeDaoImpl.add(int, int))")
     *          execution(---):执行命令
     *          简化:@Before("execution(* com.iotek.daoImpl.ComputeDaoImpl.*(..))")
     *          
     * 
     * 常用的对象:
     *  JoinPoint:获得信息:
     *  1、获得当前执行的方法名:
     *  2、获得方法中参数传递的内容
     * 
     */

     /*
      * 由于每个方法执行的内容都相同:execution(内容都相同)
      * 则将内容提起出来 PointCut
      */
    /*@Pointcut(value="execution(* com.iotek.daoImpl.ComputeDaoImpl.*(..))")
    public void qrd(){};*/

    //--设置方法执行点:
    //@Before("execution(public void com.iotek.daoImpl.ComputeDaoImpl.add(int, int))")
    //@Before("execution(* com.iotek.daoImpl.ComputeDaoImpl.*(..))")
    //@Before("qrd()")
    /*
     * 
     */
    public void xmlBefore(JoinPoint point){
        String name=point.getSignature().getName();
        List list=Arrays.asList(point.getArgs());
        System.out.println("--->xmlBefore名字是:"+name+"参数是:"+list);
    }
    public void xmlAfter(){
        System.out.println("--->xmlAfter名字是");
    }
     public void afterException(JoinPoint point,Exception ex){
            String methodName = point.getSignature().getName();
            System.out.println("--->afterException"+methodName+":异常信息:"+ex);
        }
   public void afterReturnMethod(JoinPoint point,Object res){
          String methodName=point.getSignature().getName();
            System.out.println("--->afterResultMethod方法名称是:"+methodName+"-返回值:"+res);
    }
   public void aroundMethod(JoinPoint point){
     String methodName=point.getSignature().getName();
     List list=Arrays.asList(point.getArgs());
        System.out.println("--->aroundMethod:"+methodName+"-参数:"+list);

  }
}

第六步、定义实体类

package com.iotek.dao;

public class PersonDao {
    public void add(int i, int j) {

        int sum = i /j;
        System.out.println("add==="+sum);
    }

    public int sum(int i, int j) {

        int sum = i + j;
        System.out.println("sum==="+sum);
        return sum;
    }

}

第七步、注册AOP对象

    <!-- 注册:AOP对象 -->
    <bean id="logAspect" class="com.iotek.aspect.LogAspect"></bean> 

第八步、 定义切入点 表达式:PointCut

    <!-- 定义切入点 表达式:PointCut -->
    <aop:pointcut expression="execution(* com.iotek.dao.PersonDao.*(..))" id="log"/>
       <aop:aspect ref="logAspect">      
          <aop:before method="xmlBefore" pointcut-ref="log"/>
          <aop:after method="xmlAfter" pointcut-ref="log"/>
         <aop:after method="aroundMethod" pointcut-ref="log"/> 
          <aop:after-returning method="afterReturnMethod" returning="res" pointcut-ref="log"/>
          <aop:after-throwing method="afterException" throwing="ex"  pointcut-ref="log"/>
       </aop:aspect>
    </aop:config>

第九步、测试类

package com.iotek.demo;

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

import com.iotek.dao.PersonDao;

public class Demo {
    public static void main(String args[]){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonDao person=context.getBean("person", PersonDao.class);
        person.add(10, 5);
        person.sum(2, 1);
    }

}

applicationContext.xml的完整配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    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/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

    <aop:aspectj-autoproxy proxy-target-class="true"/>
 <context:component-scan base-package="com.iotek.aspect"/> 
    <bean id="person" class="com.iotek.dao.PersonDao"></bean>
    <aop:config>

    <!-- 定义切入点 表达式:PointCut -->
    <aop:pointcut expression="execution(* com.iotek.dao.PersonDao.*(..))" id="log"/>
       <aop:aspect ref="logAspect">      
          <aop:before method="xmlBefore" pointcut-ref="log"/>
          <aop:after method="xmlAfter" pointcut-ref="log"/>
         <aop:after method="aroundMethod" pointcut-ref="log"/> 
          <aop:after-returning method="afterReturnMethod" returning="res" pointcut-ref="log"/>
          <aop:after-throwing method="afterException" throwing="ex"  pointcut-ref="log"/>
       </aop:aspect>
    </aop:config>
   </beans>

通过扫描包完成Bean的注入,需要在类中声明@Component(“logAspect”)
切面类也可以通过注解方式定义:

package com.iotek.aspect2;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LogAspect2 {
    @Before("execution(* com.iotek.dao.PersonDao.*(..))")
    public void xmlBefore(JoinPoint point){
        String name=point.getSignature().getName();
        List list=Arrays.asList(point.getArgs());
        System.out.println("--->xmlBefore名字是22222222:"+name+"参数是:"+list);
    }
    @After("execution(* com.iotek.dao.PersonDao.*(..))")
    public void xmlAfter(){
        System.out.println("--->xmlAfter名字是2222222");
    }

    @AfterThrowing(value="execution(* com.iotek.dao.PersonDao.*(..))",throwing="ex")
     public void afterException(JoinPoint point,Exception ex){
            String methodName = point.getSignature().getName();
            System.out.println("--->afterException222222"+methodName+":异常信息:"+ex);
        }
     @AfterReturning(value="execution(* com.iotek.dao.PersonDao.*(..))",returning="res")
   public void afterReturnMethod(JoinPoint point,Object res){
          String methodName=point.getSignature().getName();
            System.out.println("--->afterResultMethod方法名称是22222222222:"+methodName+"-返回值:"+res);
    }



}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值