zoukankan      html  css  js  c++  java
  • Spring/AOP框架, 以及使用注解

    1, 使用代理增加日志, 也是基于最原始的办法

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class LoggingProxy {
        /*
         * 代理类, 基于接口
         */
        //要被代理的对象, 目标对象
        private Icalculator target;
        //生成一个构造方法
        public LoggingProxy(Icalculator target) {
            super();
            this.target = target;
        }
        //应用通知. 并产生对象
        public Icalculator getProxy() {
            Icalculator ica = null;
            //应用通知
            //获得类加载器: ClassLoader, 类加载器在getClass()方法里面
            ClassLoader cl = target.getClass().getClassLoader();
            
            //获得class中所有方法的数组, 数组的内容一定要是接口.class
            Class[] cla= new Class[] {Icalculator.class};
            //Class[] al = new Class[] {IJiSuanQi.class};//接口
            
            //获得
            InvocationHandler ih = new InvocationHandler() {
                @Override
                //调用invoke的时候就是实现一个切面编程
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //在这之前可以增加数据验证
                    Object obj = null;
                    System.out.println(method.getName()+" 开始调用");
                    try {
                        obj = method.invoke(target, args);
                    }
                    catch(Exception e) {
                        System.out.println("异常通知: "+method.getName());
                    }
                    System.out.println(method.getName()+" 结束调用");
                    return obj;
                }
            };
            //产生代理对象, 引用了反射的jar包
            ica = (Icalculator)Proxy.newProxyInstance(cl, cla, ih);
            return ica;
        }
    }

    2, 使用AOP框架

    配置文件

        <!-- 前面定义的类class -->
        <bean id="cal" class="com.hanqi.Calculator">
        </bean>
        
        <!-- 切面类 -->
        <bean id="la" class="com.hanqi.LoggingAspect">
        </bean>
        
        <!-- 定义AOP -->
        <aop:config>
        <!-- 配置切点表达式, 被切入的方法 -->
        <!-- expression写对象必须是个接口被切入方法的名字, 如果要写所有的方法就用*号表示 -->
            <aop:pointcut expression="execution(* com.hanqi.Icalculator.*(int,int))" id="loggingpointcut"/>
            
            <!-- 配置切面和通知 -->
            <aop:aspect ref="la">
                <!-- 方法前通知 -->
                <aop:before method="beforeMethod" pointcut-ref="loggingpointcut"/>
                <aop:after method="afterMethod" pointcut="execution(* com.hanqi.Icalculator.cheng(int,int))"/>
                <aop:after-throwing method="exceptionMethod" pointcut-ref="loggingpointcut" throwing="ex"/>
                <aop:after-returning method="returnMethod" pointcut-ref="loggingpointcut" returning="obj"/>
            </aop:aspect>
            
        </aop:config>

    定义切面类

    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    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;
    
    public class LoggingAspect {
        //切面类, 前置通知
        public void beforeMethod(JoinPoint jp) {
            //获取方法名
            String str = jp.getSignature().getName();
            //返回一个参数列表
            Object[] obj = jp.getArgs();
            System.out.println("方法名 = "+str);
            System.out.println(Arrays.asList(obj));
            System.out.println("这里是方法前的通知");
        }
        public void afterMethod(JoinPoint jp) {
            System.out.println("这里是方法后的通知");
        }
        //异常通知
        public void exceptionMethod(JoinPoint jp,Exception ex) {
            System.out.println("异常信息"+ex);
        }
        
        //返回通知
        public void returnMethod(JoinPoint jp,Object obj) {
            System.out.println("返回通知的结果: "+obj);
        }
    }

    3, 使用注解的方式(标红的部分是注解), 一定记得写上返回值和, expression表达式

    import org.springframework.stereotype.Component;
    
    @Component("cal")
    public class Calculator implements Icalculator {
        ......
        方法体
        ......
    }
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    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;
    
    @Aspect
    @Component
    public class LoggingAspect {
        //切面类, 前置通知
        @Before(value = "execution(* com.hanqi.Calculator.*(..))")
        public void beforeMethod(JoinPoint jp) {
            //获取方法名
            String str = jp.getSignature().getName();
            //返回一个参数列表
            Object[] obj = jp.getArgs();
            System.out.println("方法名 = "+str);
            System.out.println(Arrays.asList(obj));
            System.out.println("这里是方法前的通知");
        }
        //后置通知
        @After("execution(* com.hanqi.Calculator.*(..))")
        public void afterMethod(JoinPoint jp) {
            System.out.println("这里是方法后的通知");
        }
        //异常通知
        @AfterThrowing(pointcut="execution(* com.hanqi.Calculator.*(..))", throwing="ex")
        public void exceptionMethod(JoinPoint jp,Exception ex) {
            System.out.println("异常信息"+ex);
        }
        
        //返回通知
        @AfterReturning(pointcut="execution(* com.hanqi.Calculator.*(..))", returning="obj")
        public void returnMethod(JoinPoint jp,Object obj) {
            System.out.println("返回通知的结果: "+obj);
        }
    }

     注解的配置文件

    <?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/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
            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.2.xsd">
    
    <!-- 使用注解的方式 -->
    <!-- 扫描器 -->
    <context:component-scan base-package="com.hanqi"></context:component-scan>
    <!-- 启用AOP注解 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>
  • 相关阅读:
    对生产稳定的一些思考
    tsar指标解释
    tsar采集nginx指标
    Nginx如何处理一个连接
    Java : 如何更优雅的设计异常
    MySql的索引实现
    IntelliJ Idea 常用配置
    ICSharpCode.SharpZipLib.dll 压缩、解压Zip文件 附源码
    Java BigDecimal使用
    社交系统中用户好友关系数据库设计
  • 原文地址:https://www.cnblogs.com/wgbs25673578/p/5164849.html
Copyright © 2011-2022 走看看