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

    日志,后置通知

     
  • 相关阅读:
    JS自定义事件之选项卡
    架构MVC——JS中的理论
    jquery嵌套后会触发2次点击事件, jquery的unbind就是卸载这个点击事件的.
    【js与jquery】javascript中url编码与解码
    使用jquery获取url以及jquery获取url参数的方法
    js 正则匹配 小结
    Web前端开发规范文档
    HTTP及XMLHTTP状态代码一览
    css命名规则
    JS四级复选框选中层次关系
  • 原文地址:https://www.cnblogs.com/xuesheng/p/7455391.html
Copyright © 2011-2022 走看看