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>
原文地址:https://www.cnblogs.com/wgbs25673578/p/5164849.html