导航

Spring3 AOP的使用

Posted on 2012-10-31 11:40  曙光城邦  阅读(2997)  评论(0编辑  收藏  举报

Spring的两大核心功能IOC(控制反转)和AOP(面向切面编程)用于项目各层次的解耦及非入侵式开发和简化开发和维护成本,根据需求可用于任何java项目。

目标:使用Spring的面向切面编程AOP(Aspect Oriented Programming).

备注:个人理解,切面表现在编程里就是针对对象方法的拦截,如方法执行前或执行后执行一段代码。面向对象中对象是一个整体,切面则是横向思考的一种方式。

准备工作:
1.下载spring
下载后的压缩包为spring-3.2.0.M2-dist.zip,为spring3.2版本.
2.下载commons-logging.jar文件,spring依赖这个jar,否则运行异常,用于日志输出  下载地址:地址:http://commons.apache.org/logging/download_logging.cgi。
3.aspectj.jar  aspectjweaver.jar aopalliance.jar,是切面开发需要的包。我下到的是aspectj-1.6.10.jar,aspectjweaver-1.5.3.jar,aopalliance.jar
4.cglib-nodep.jar  ,cglib用于无实现接口对象的代理对象生成。我下到的是cglib-nodep-2.1_3.jar


工程搭建:
一、新建一个  Java Project
二、导入jar包
经过测试spring运行ioc最少导入以下4个包:
spring-core-3.2.0.M2.jar
spring-context-3.2.0.M2.jar
spring-beans-3.2.0.M2.jar
spring-expression-3.2.0.M2.jar
spring-aop-3.2.0.M2.jar
然后导入
commons-logging-1.1.1.jar
aspectj-1.6.10.jar,aspectjweaver-1.5.3.jar,aopalliance.jar
cglib-nodep-2.1_3.jar


好了,环境搭好了,然后就是新建类并在xml中描述该类的实例化方式。
这里使用applicationContext.xml描述.
相关描述说明看文档spring-3.2.0.M2/docs/reference/html/beans.html

代码:

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:p="http://www.springframework.org/schema/p" 
    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-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    ">
       
    <!-- 包扫描,注册了各种处理器,包括Controller Service Component注解等的处理器 -->
    <context:component-scan base-package="com.zk.*"/>
    <!-- aop自动代理配置,配置后直接使用注解 -->
    <aop:aspectj-autoproxy/>
</beans>

StudentAction.java

package com.zk.action;

import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.stereotype.Controller;

@Controller
public class StudentAction {
    private String name="zhangsan";
    
    public String getName(){
        System.out.println("StudentAction getName()执行了");
        return name;
    }
    
    public void setName(String name){
        this.name=name;
        System.out.println("StudentAction setName()执行了2");
        //如果抛出异常,则@AfterReturning后置通知将不执行。
        //前置通知,最终通知,异常通知将执行,并抛出异常
        //throw new RuntimeException();
    }
}

StudentActionAOP.java

package com.zk.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class StudentActionAOP {

    @Before("execution(* com.zk.action.*.*(..))")
    public void beforeInvoke(){
        System.out.println("aop 拦截 ,前置通知");//目标对象的方法执行前执行
    }
    
    @AfterReturning("execution(* com.zk.action.*.*(..))")
    public void afterInvoke(){
        System.out.println("aop 拦截 ,后置通知");//目标对象的方法正常执行后执行
    }
    
    @After("execution(* com.zk.action.*.*(..))")
    public void afterReturnInvoke(){
        System.out.println("aop 拦截 ,最终通知");//目标对象的方法无论正常还是异常都执行,即try{}catch(){}finally{}中finally代码段
    }
    
    @AfterThrowing("execution(* com.zk.action.*.*(..))")
    public void exceptionInvoke(){
        System.out.println("aop 拦截 ,异常通知");//目标对象的方法抛出异常将执行
    }
}

Main.java

package com.zk.main;

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

import com.zk.action.StudentAction;

public class Main {
    
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        StudentAction studentAction = (StudentAction)ctx.getBean("studentAction");
        studentAction.setName("lisi");
    }
    
}

 

运行结果:

aop 拦截 ,前置通知
StudentAction setName()执行了2
aop 拦截 ,最终通知
aop 拦截 ,后置通知

 

 

=============================================

使用切面表达式定义切面

package com.zk.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class StudentActionAOP {
    
    @Pointcut("execution(* com.zk.action.*.*(..))")//切面定义表达式
    public void myPointCut(){}//切面名称 myPointCut()
    
    //--------------
    //定义一个Pointcut,然后将各个通知应用到某个切面上,切面可以使用多个
    //--------------

    @Before("myPointCut()")
    public void beforeInvoke(){
        System.out.println("aop 拦截 ,前置通知");//目标对象的方法执行前执行
    }
    
    @AfterReturning(pointcut="myPointCut()",returning="retVal")
    public void afterInvoke(Object retVal){
        System.out.println("aop 拦截 ,后置通知"+";retVal="+retVal);//目标对象的方法正常执行后执行
        
    }
    
    @After("myPointCut()")
    public void afterReturnInvoke(){
        System.out.println("aop 拦截 ,最终通知");//目标对象的方法无论正常还是异常都执行,即try{}catch(){}finally{}中finally代码段
    }
    
    @AfterThrowing(pointcut="execution(* com.zk.action.StudentAction.*(..))")
    public void exceptionInvoke(){
        System.out.println("aop 拦截 ,异常通知");//目标对象的方法抛出异常将执行
    }
}

输出结果:

aop 拦截 ,前置通知
StudentAction setName()执行了2
aop 拦截 ,最终通知
aop 拦截 ,后置通知;retVal=null

 

如果出现 error at ::0 can't find referenced pointcut allAllMethod1   错误,则是aspectjweaver.jar包错误。

换个jar包就可以正确解析表达式了。我这里使用的是 aspectjweaver-1.7.1.jar

aspectjweaver.jar下载 --> http://search.maven.org/  搜索  aspectjweaver  选择下载1.7.1的jar包就可以了。


!临时找jar包去哪里找呢?

上maven中央仓库搜索! 这是地址:http://search.maven.org/