Spring AOP 详解(jdk和cglib动态代理)

1.cgLib 动态代理:

目标对象:

package proxy.cglib;
public class Student {
   

    public  String say(String message){
   
        System.out.println("学生:"+message);
        return  message;
    }
}

代理模板:

package proxy.cglib;

import com.alibaba.fastjson.JSON;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * Created by zhangzhanhao on 2019/12/14
 */
public class LogProxy  implements MethodInterceptor {
   


    public Object CreatProxyedObj(Class<?> clazz)
    {
   
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
   
        System.out.println("请求日志:"+method.getName()+":"+ JSON.toJSONString(objects));
        return  methodProxy.invokeSuper(o,objects);

    }
}

package proxy.cglib;

/**
 * Created by zhangzhanhao on 2019/12/14
 */
public class MainDemo {
   

    public static void main(String[] args) {
   
        LogProxy logProxy = new LogProxy();
        Student student =   (Student)logProxy.CreatProxyedObj(Student.class);

        student.say("this is cglib proxy ");

    }
}

打印结果:
请求日志:say:["this is cglib proxy "]
学生:this is cglib proxy

2. jdk动态代理:

目标对象:

package proxy.jdk;


public interface People {
   
    public String say(String message);
}



public class worker implements  People {
   

    @Override
    public String say(String message) {
   

        System.out.println("工人:"+message);
        return message;
    }
}

代理模板:

package proxy.jdk;

import com.alibaba.fastjson.JSON;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class LogWorkerProxy  implements InvocationHandler {
   

    private Object targetObject;

    public Object createProxy(Object object){
   
        this.targetObject = object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
   
        System.out.println("请求日志:"+method.getName()+":"+ JSON.toJSONString(objects));
        return method.invoke(targetObject,objects);
    }
}

package proxy.jdk;


public class MainTest  {
   

    public static void main(String[] args) {
   
        LogWorkerProxy logWorkerProxy = new LogWorkerProxy();
        People people =  (People)logWorkerProxy.createProxy(new worker());
        people.say("this is jdk proxy");
    }
}

打印结果:
请求日志:say:[“this is jdk proxy”]
工人:this is jdk proxy

3.实现Aop

Aop: 就是面向切面编程。

aop实现有两种框架:Spring Aop 和 Aspectj。

Spring Aop 和 Aspectj 是实现aop的两种框架,处于竞争关系。

为什么Spring 中(官方文档和框架中) 会出现 AspectJ。 因为 在Spring 2.5 的时候,spring Aop 实现 aop(面向切面编程)的时候,语法非常的复杂,很不受开发人员喜欢,而AspectJ的语法非常简单。Spring 就借用了AspectJ语法 。注意这里只是借用AspectJ的语法。所以Spring Aop 中 才会出现AspectJ 注解和类似的配置。

Spring Aop 以下讲解都以注解风格配置:

在spring boot 启动类中加:@EnableAspectJAutoProxy
启动:Spring Aop 自动代理(Spring Aop 中怎么会出现 AspectJ的身影,那是因为Spring Aop 实现的时候 参考了 AspectJ的 风格)

Aop 可以做统一日志 和异常处理:
定义切面:

package com.log;

import com.alibaba.fastjson.JSON;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 日志切面类
 */
@Aspect  /*1.声明一个切面:链接点,切点 和 通知 所在的那个类 就叫切面*/
@Component
@Order(5)
public class WebLogAspect {
   
    private Logger logger=Logger.getLogger(getClass());
    private ThreadLocal<Long> startTime=new ThreadLocal<>();

   /** 2. Spring Aop  是通过增加一个方法来增加一个类的
    *  2.1 类中的每个方法称之为链接点。
    *  2.2  链接点(方法)的集合 称为切=点。
   */
    @Pointcut("execution( * com.controller.*.*(..))")
    public void webLog(){
   }

    /**
     * 通知:分为两个维度  1.切入链接(方法)点的时机,如方法前,方法后,或者抛异常的时候。
     * 2.织入的内容是什么 比如打印日志,或开启事物。
     * @param point
     */
    @Before(value = "webLog()")
    public void doBefore(JoinPoint point){
   
        logger

你可能感兴趣的:(java,spring,jdk)