• spring-aop学习【基于注解】


    我个人觉得,这个好像就是用在定制日志输出上,和log4j很像。

    用途:

    如果业务方法调用每一步都需要详细的日志,那就用这个吧

    好处就是:

    方便维护,只包含业务代码

    下面开始说明:

    所需要的jar包:

    com.springsource.net.sf.cglib-2.2.0.jar
    com.springsource.org.aopalliance-1.0.0.jar
    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
    commons-logging-1.1.1.jar
    spring-aop-4.0.0.RELEASE.jar
    spring-aspects-4.0.0.RELEASE.jar
    spring-beans-4.0.0.RELEASE.jar
    spring-context-4.0.0.RELEASE.jar
    spring-core-4.0.0.RELEASE.jar
    spring-expression-4.0.0.RELEASE.jar

    直接上代码:

    声明一个接口

    package com.spring.bean.aop;
    
    import java.util.List;
    
    /**
     * 
     * @author Administrator
     *
     */
    public interface UserService {
    //    打招呼
        void say();
    //    获取年龄
        int getValue(List<Integer> array,int index);
    }

    这是接口的实现类

    package com.spring.bean.aop;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * 
     * @author Administrator
     *      实现类
     */
    @Service("userService")
    public class UserServiceImpl implements UserService {
    
        /**
         * 自动装配use对象
         */
        @Autowired
        private User user;
        @Override
        public void say() {
            // TODO Auto-generated method stub
            System.out.println("我叫"+user.getName()+",今年"+user.getAge()+"岁,你好!!");
        }
        
        @Override
        public int getValue(List<Integer> array, int index) {
            // TODO Auto-generated method stub
            return array.get(index);
        }
    
    
    }

    用户对象信息

    package com.spring.bean.aop;
    
    import org.springframework.stereotype.Component;
    
    /**
     * @author Administrator
     *      用户信息
     */
    @Component
    public class User {
    
        String name;
        int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }

    然后是两个切面代码

    package com.spring.bean.aop;
    
    import java.util.Arrays;
    
    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;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    /**
     * 声明一个切面
     * @author Administrator
     *
     */
    //order可以指定哪个切面先执行,数值越小,优先执行
    @Order(1) @Aspect @Component public class MyLoggingAspectj { // 声明一个切入点 @Pointcut("execution(* *(..))") public void pointcut(){ } /** * 前置通知,该方法执行在被调用方法之前 * @param joinPoint */ @Before("pointcut())") public void beforeMethod(JoinPoint joinPoint){ // 获得调用的方法名 String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("MyLoggingAspectj the method "+methodName+"begins with "+Arrays.asList(args)); } }
    第二个切面代码
    package com.spring.bean.aop;
    
    import java.util.Arrays;
    
    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;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    /**
     * 声明一个切面
     * @author Administrator
     *
     */
    @Order(2)
    @Aspect
    @Component
    public class LoggingAspectj {
        
        
    //    声明一个切入点
        @Pointcut("execution(* *(..))")
        public void pointcut(){
            
        }
    
    /*    *//**
         * 前置通知,该方法执行在被调用方法之前
         * @param joinPoint
         *//*
        @Before("pointcut())")
        public void beforeMethod(JoinPoint joinPoint){
    //        获得调用的方法名
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            System.out.println("the method "+methodName+"begins with "+Arrays.asList(args));
        }
        
        *//**
         * 后置通知
         * 该方法执行在被调用方法之后,报错也依然执行
         * @param joinPoint
         *//*
        @After("pointcut())")
        public void afterMethod(JoinPoint joinPoint){
    //        获得调用的方法名
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            System.out.println("the method "+methodName+"Ends with "+Arrays.asList(args));
        }
        
        *//**
         * 返回通知, 在方法返回结果之后执行,异常无返回值
         * @param joinPoint
         *//*
        @AfterReturning(value="pointcut())",returning="result")
        public void afterReturning(JoinPoint joinPoint,Object result){
    //        获得调用的方法名
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            System.out.println("the method "+methodName+"afterReturning with "+Arrays.asList(args)+"  ["+result+"]");
        }
        
        *//**
         * 异常通知
         * 在方法抛出异常之后
         * @param joinPoint
         *//*
        @AfterThrowing(value="pointcut()",throwing="e")
        public void afterReturning(JoinPoint joinPoint,Exception e){
    //        获得调用的方法名
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            System.out.println("the method "+methodName+"afterThrowing with "+Arrays.asList(args)+e);
        }*/
        
        /**
         * 环绕通知需要配合ProceedingJoinPoint使用,相当于动态代理
         * @param pjp
         * @return
         */
        @Around(value="pointcut()")
        public Object aroundMethod(ProceedingJoinPoint pjp) {
            // 获得调用的方法名
            String methodName = pjp.getSignature().getName();
            Object result = null;
            // 调用目标方法
            try {
                // 前置通知
                System.out.println("the method " + methodName + "Begins with " + Arrays.asList(pjp.getArgs()));
                result = pjp.proceed();
                // 后置通知
                System.out.println("the method " + methodName + "Ends with " + Arrays.asList(pjp.getArgs()));
                // 后置有返回值
                System.out.println(
                        "the method " + methodName + "Ends with " + Arrays.asList(pjp.getArgs()) + " [" + result + "]");
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                // 异常通知
                System.out.println("the method " + methodName + "AfterThrowing with " + Arrays.asList(pjp.getArgs()) + e);
                // e.printStackTrace();
                // 不加这句,会报错,因为result返回值为null
                throw new RuntimeException(e);
            }
            System.out.println("the method " + methodName + "LastEnds with " + Arrays.asList(pjp.getArgs()));
            return result;
        }
        
        
    }
    
    

    测试代码:

    package com.spring.bean.aop;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            ApplicationContext ctx=new ClassPathXmlApplicationContext("bean-aop.xml");
            UserService userServiceImpl=(UserService) ctx.getBean("userService");
            User user=(User) ctx.getBean("user");
            List<Integer> arrayList = new ArrayList<Integer>();
            arrayList.add(1);
            arrayList.add(2);
            int age = userServiceImpl.getValue(arrayList, 1);
            user.setName("xiaoqiang");
            user.setAge(age);
            userServiceImpl.say();
        }
    
    }

    bean文件

    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:p="http://www.springframework.org/schema/p"
        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-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
        <!-- 自动扫描的包 -->
        <context:component-scan base-package="com.spring.bean.aop"></context:component-scan>
        <!-- 使 AspectJ 的注解起作用 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    </beans>
     总结:
    1.在pom文件添加依赖,在 Spring 的配置文件中加入 aop 的命名空间。 
        <!--使用AspectJ方式注解需要相应的包-->  
             <dependency>  
                <groupId>org.aspectj</groupId>  
                <artifactId>aspectjrt</artifactId>  
                <version>${aspectj.version}</version>  
            </dependency>  
             <!--使用AspectJ方式注解需要相应的包-->  
            <dependency>  
                <groupId>org.aspectj</groupId>  
                <artifactId>aspectjweaver</artifactId>  
                <version>${aspectj.version}</version>  
            </dependency> 
    
    

    2.为接口实现类添加注解@Component

    3.编写一个切面类,配置切面

    * 3.1 在配置文件中配置自动扫描的包: <context:component-scan base-package="com.spring.bean.aop"></context:component-scan>

    * 3.2 加入使 AspjectJ 注解起作用的配置: <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    * 为匹配的类自动生成动态代理对象.

    4.编写前置通知方法,在方法上方添加注解

    // 表达式注意格式: 修饰 +方法(有无返回)+包名+类名+方法名+参数


      @Before("execution(public int com.spring.bean.annotation.aopimpl.Calculation.sub(int, int))")

    * @Before 表示在目标方法执行之前执行 @Before 标记的方法的方法体.
    * @Before 里面的是切入点表达式:

    如关注详细参数,添加joinpoint对象,可以访问到方法的签名和参数

  • 相关阅读:
    B题 hdu 1407 测试你是否和LTC水平一样高
    A题 hdu 1235 统计同成绩学生人数
    hdu 1869 六度分离(最短路floyd)
    hdu 2795 Billboard(线段树+单点更新)
    hdu 1754 I Hate It(线段树)
    hdu 1166敌兵布阵(线段树)
    hdu 1556(线段树之扫描线)
    Contest2073
    中南oj String and Arrays
    51nod 1459 迷宫游戏 (最短路径—Dijkstra算法)
  • 原文地址:https://www.cnblogs.com/longronglang/p/6243251.html
Copyright © 2020-2023  润新知