zoukankan      html  css  js  c++  java
  • Spring3 AOP的使用

    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/

  • 相关阅读:
    WPF-模拟动态更换logo的过程(3),图片正在使用中,下载同名图片无法覆盖的问题。
    WPF-模拟动态更换logo的过程(2),如何把网上的图片下载到指定目录。
    WPF-模拟动态更换logo的过程(1),如何获取程序的根目录。
    Prism——Window 必须是树的根目录。不能将 Window 添加为 Visual 的子目录。
    一款常用的截图工具(能够截gif动图)
    WPF-带有GridView的ListView样式
    WPF-自定义实现步骤条控件
    分页总页数计算公式
    FileZilla:425 Can't open data connection for transfer of解决办法
    查看window重启日志
  • 原文地址:https://www.cnblogs.com/beenupper/p/2747772.html
Copyright © 2011-2022 走看看