zoukankan      html  css  js  c++  java
  • 简单版的AOP实现日志打印功能

    需要的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.3. 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

    一、创建一个接口

      

    public interface MyMath {
    public int add(int i,int j);
    public void sub(int i,int j);
    public void mul(int i,int j);
    public void div(int i,int j);
    }

    二、创建一个类实现上面的接口

      这里使用了@component注解的方式将MymathImpl对象注入到IOC容器中

    @Component
    public class MyMathImpl implements MyMath{
    
        @Override
        public int add(int i, int j) {
            int result=i+j;
            System.out.println("目标方法add执行了, "+result);
            return result;
            
        }
    
        @Override
        public void sub(int i, int j) {
            // TODO Auto-generated method stub
            int result=i-j;
            System.out.println("目标方法sub执行了, "+result);
        }
    
        @Override
        public void mul(int i, int j) {
            // TODO Auto-generated method stub
            int result=i*j;
            System.out.println("目标方法mul执行了, "+result);
        }
    
        @Override
        public void div(int i, int j) {
            // TODO Auto-generated method stub
            int result=i/j;
            System.out.println("目标方法div执行了, "+result);
        }
    }

    因为使用注解,所以在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-3.2.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">
        <1--扫描包-->
         <context:component-scan base-package="com.neuedu"></context:component-scan>
    </beans>

    三、创建一个切面类  

      1.开启基于注解的AOP功能
      < aop:aspectj-autoproxy />

      需要在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: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/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">
         
         <!--扫描包  -->
         <context:component-scan base-package="com.neuedu.bean"></context:component-scan>
     <!-- 开启AOP注解 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>

      2.声明一个切面类,并把这个切面类加入到IOC容器中
      @Aspect//表示这是一个切面类
      @Component//加入IOC容器

    @Component
    @Aspect
    public class MyMathAspect {
        @Pointcut(value="execution(public * com.neuedu.bean.MyMathImpl.*(..))")
        public void showLog(){
        }  
    @Before(value
    = "showLog()") public void showBeforLog(JoinPoint point ){ Object[] args = point.getArgs(); List<Object> asList = Arrays.asList(args); Signature signature = point.getSignature(); String name = signature.getName(); System.out.println("日志,前置通知,参数为:"+name+"方法为:"+asList); } @After(value = "showLog()") public void showAfterLog(){ System.out.println("日志,后置通知"); } @AfterThrowing(value = "showLog()",throwing="ex") public void showAfterThrowingLog(Exception ex){ System.out.println("日志,异常通知,异常信息为 "+ex); } @AfterReturning(value = "showLog()",returning="result") public void showAfterReturningLog(Object result){ System.out.println("日志,返回置通知,结果为: "+result); } }

    3.说明:1)   [1]前置通知:@Before
                [2]返回通知:@AfterReturning
           [3]异常通知:@AfterThrowing
           [4]后置通知:@After

         2) execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表])) 

          如果execution写成excution在applicationcontext.xml 中扫描包会出现问题。

          value="execution(public * com.neuedu.bean.MyMathImpl.*(..))"

          支持通配符 第一个*代表了任意的返回类型,第二*代表了该类下任意的方法,..代表任意的参数类型和个数。

          最详细的切入点表达式:
            execution(public int com.neuedu.aop.target.MathCalculatorImpl.add(int, int))
          最模糊的切入点表达式:
            execution (* *.*(..))

      

        用@PointCut注解统一声明,然后在其它通知中引用该统一声明即可!
        需要注意的是:权限是不支持写通配符的,当然你可以写一个*表示所有权限所有返回值!

        3)通知方法的细节,参数

            a).通知方法中有一个JoinPoint类型的参数

               可以获取目标方法的签名,进而获取方法名 

                   Signature signature = point.getSignature();
                      String name = signature.getName();
             可以获取方法的参数,不过需要转换:          
                 Object[] args = point.getArgs();
                    List<Object> asList = Arrays.asList(args);
             b) 在返回通知中获取方法的返回值     

                [1]在@AfterReturning注解中添加returning属性
                @AfterReturning (value="myPointCut()", returning= "result")
                [2]在返回通知的通知方法中声明一个形参,形参名和returning属性的值一致
                showReturnLog(JoinPoint joinPoint, Object result)
                [3]在异常通知中获取异常对象
                  [1]在@ AfterThrowing注解中添加throwing属性
                  @AfterThrowing (value="myPointCut()",throwing= "throwable" )
                  [2]在异常通知的通知方法中声明一个形参,形参名和throwing属性值一致
                  showExceptinLog(JoinPoint joinPoint, Throwable throwable)

     四、创建一个测试类:
        
    public class IOCTest {
        
        private ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
    
        @Test
        public void test() {
            /*Object bean = ioc.getBean("myMathImpl");
            System.out.println(bean);*/
            MyMath bean2 = ioc.getBean(MyMath.class);
            bean2.add(10, 2);
        }
    
    }

    执行结果:

    日志,前置通知,参数为:add方法为:[10, 2]
    目标方法add执行了, 12
    日志,后置通知
    日志,返回置通知,结果为: 12

    当出现异常:除法中一个数除以0 会出现异常

      

    public class IOCTest {
        
        private ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
    
        @Test
        public void test() {
            /*Object bean = ioc.getBean("myMathImpl");
            System.out.println(bean);*/
            MyMath bean2 = ioc.getBean(MyMath.class);
            bean2.div(10, 0);
        }
    }

    执行结果为:

    日志,前置通知,参数为:div方法为:[10, 0]

    java.lang.ArithmeticException: / by zero

    日志,后置通知

     
  • 相关阅读:
    547. Friend Circles
    399. Evaluate Division
    684. Redundant Connection
    327. Count of Range Sum
    LeetCode 130 被围绕的区域
    LeetCode 696 计数二进制子串
    LeetCode 116 填充每个节点的下一个右侧节点
    LeetCode 101 对称二叉树
    LeetCode 111 二叉树最小深度
    LeetCode 59 螺旋矩阵II
  • 原文地址:https://www.cnblogs.com/xuesheng/p/7455391.html
Copyright © 2011-2022 走看看