静态代理与动态代理

相同:AOP、都可以用来做增强
静态代理
动态代理有两种-JDK动态代理和CGLIB动态代理

spring会使用哪种代理方式呢?

1、如果代理目标对象实现了接口,那么会默认使用jdk动态代理,代理对象是接口也可以设置强制使用cglib代理方式,如果代理目标对象只是一个普通对象,并没有实现接口,那么会使用CGLIB代理

为什么jdk代理基于接口实现?

因为在jdk代理中,获取代理目标对象的方法是通过使用Object.getClass.getInteface方法来生成代理实例对象
而,cglib代理则是通过增强器来设置代理类,获取到对象
JDK代理不需要依赖第三方的库,只要安装了JDK环境就可以进行代理,代理实现逻辑:
实现InvocationHandler接口,重写invoke()
使用Proxy.newProxyInstance()产生代理对象,方法入参【ClassLoader loader, Class<>[] interfaces, InvocationHandler h】
要求:被代理的对象必须要实现接口
CGLib 必须依赖于CGLib的类库,代理实现逻辑:
实现MethodInterceptor接口,重写intercept()
使用Enhancer对象.create()产生代理对象

JDK动态代理:

基于接口实现
实现的是InvocationHandler接口,重写invoke方法,增强操作就在这个方法里面做,对外提供一个获取代理对象的方法。


import lombok.extern.slf4j.Slf4j;

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

/**
 * 基于接口的jdk动态代理
 */
@Slf4j
public class DynamicProxyInterface implements InvocationHandler {
    private Object obj;

    /**

     * @description: 传入目标对象,获取代理对象
  
     */
    public Object getProxyObj(Object target) {
        obj = target;

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    /**
     
     * @description: 目标对象的方法被调用的时候,可以加入增强处理
 
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //目标对象的方法被调用之前的增强处理,doSomething
        log.info(method.getName());
        Object o = method.invoke(obj, args);
        //目标对象的方法被调用之后的增强处理,doSomething                
        log.info(method.getName());
        return o;
    }
    
     //测试
    public static void main(String[] args) {
    UserService userService = new UserService();
    TestJDKAOP testJDKAOP = new TestJDKAOP();
    UserService userServiceProxy = (UserService) testJDKAOP.getProxyObj(userService);
    //代理对象,调用对象里的方法都会执行invoke里面的增强操作
    userServiceProxy.getUserInfo()
    }
}

CGLIB动态代理

CGLib使用一个增强器Enhancer,设置传入的代理对象类型,enhancer有一个拦截方法(回调函数)setCallback,在此方法内部回调实现了MethodInterceptor接口的类,类里面做增强逻辑

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author Administrator
 */
@Slf4j
public class DynamicProxyCglib {
    /**

     * @description: 传入目标对象的类型,获取代理对象
    
     */
    public Object getProxyObject(Class<?> clazz) {
        //定义字节码增强器
        Enhancer enhancer = new Enhancer();
        //通过增强器设置代理对象的类型
        enhancer.setSuperclass(clazz);
        //给增强器设置回调函数
        //方法的拦截器、此处直接用lambda直接实现MethodInterceptor
        enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
            //目标对象的方法被调用之前的增强处理,doSomething
            log.info(method.getName());
            //目标对象的方法被调用,此处必须使用methodProxy.invokeSuper,防止被拦截器循环拦截
            Object invoke = methodProxy.invokeSuper(o, objects);
            //目标对象的方法被调用之后的增强处理,doSomething
            log.info(method.getName());
            return invoke;
        });
        //执行增强器,返回代理对象
        return enhancer.create();
    }
}
//测试
    public static void main(String[] args) {
        NeedToProxyObject needOject = new NeedToProxyObject();
        //使用cglib获取代理对象(入参为class)
        DynamicProxyCglib dpc = new DynamicProxyCglib();
        NeedToProxyObject proxyObject = (NeedToProxyObject)dpc.getProxyObject(NeedToProxyObject.class);
        //调用对象方法
        ...
    }