JDK和CGLIB动态代理

动态代理

静态代理

package cn.cdqf.proxy;

public interface ScanService {

     void scan();
}

package cn.cdqf.proxy;

/**
 * 被代理类
 */
public class ScanServiceImpl implements ScanService{

    public void scan(){
        //非业务逻辑 不应该跟业务逻辑代码耦合...
        //System.out.println("记录:某某某---2020-12-10访问了篮球方面");
        System.out.println("某某某需要篮球方面的数据");
        //非业务逻辑 不应该跟业务逻辑代码耦合...
        //System.out.println("记录:某某某---2020-12-10结束了访问");
    }
}

package cn.cdqf.proxy;

/**
 * 应该与被代理类实现同一个接口
 * 这样才能在一定程度上保证 方法规则统一性
 *
 * 完全可以在这个类上面去做标记 告诉spring我要代理哪个类,被代理的类压根不知道什么情况
 *
 * 每个接口下面都会有自己的方法,你这里得调用具体得方法,所以只能代理一类对象,
 * 静态得写死方法名,静态的代理一类对象
 */
public class ScanServiceImplProxy implements ScanService{
    private ScanService scanService;

    public ScanServiceImplProxy(ScanService scanService){
        this.scanService = scanService;
    }
    @Override
    public void scan() {
        System.out.println("记录:某某某---2020-12-10访问了篮球方面");
        scanService.scan();
        System.out.println("记录:某某某---2020-12-10结束了访问");
    }
}

package cn.cdqf.proxy;

public class Test {
    public static void main(String[] args) {
        ScanService scanService = new ScanServiceImpl();
        //如果是通过spring框架来实现,@Autowired ScanService scanService
        //用户想要这样一个对象,而且在最开始创建的时候,我们可以使用标记的办法告诉spring别用我自己
        //用代理类,spring放入ioc容器中的已经是代理类
        ScanService scanServiceProxy = new ScanServiceImplProxy(scanService);
        scanServiceProxy.scan();

    }
}

动态代理

1.你调用哪个方法,我就获得这个方法,方法对象method.invoke

2.程序员不手写类,让java帮我们生成,类加载器ClassLoader

这些功能java都已经提供好了类来实现

静态代理:只能代理一部分类,需要我们去写好整个要生成class的java文件

动态代理:可以代理任意类,我们只需要告诉程序生成class的必要条件

​ 有两个方案,可以实现我们告诉程序这些必要条件

​ jdk动态代理,cglib动态代理

jdk动态代理
package cn.cdqf.proxy;

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

/**
 * 步骤
 * 1.实现InvocationHandler接口
 */
public class MyJdkProxy implements InvocationHandler {
    Object object;
    //object:被代理的类
    public MyJdkProxy(Object object){
        this.object = object;
    }
    /**
     * 增强一个方法:在方法前,方法正常结束后,方法抛异常后,方法无论抛不抛异常后
     * @param proxy
     * @param method:代表现在正在调用的方法
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //增强的逻辑
        System.out.println("方法调用前增强逻辑。。。。");
        //增强不增强,原来的逻辑不能变,原方法该调用还得调用  调用的原来scan
        Object invoke = method.invoke(object, args);
        System.out.println("方法调用后增强逻辑。。。。");
        return invoke;
    }
    //把被代理类给我了 我要调用一个方法去生成代理类
    public Object getInstance(){
        //proxy是jdk提供的代理类,生成代理类的方法
        //因为要求方法名相同:jdk选择了接口
        /**
         * 类加载:加载功能
         * 被代理类实现的接口:为了统一方法名
         * 代理的功能,要如何增强,大家都乱写jdk不知道写在哪里的,jdk就要求必须传一个实现了
         * InvocationHandler的类,然后把增强逻辑写在invoke方法中
         *
         * jdk生成的代理类 会跟被代理类实现同一个接口
         */
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces()
        ,this);
    }
}

public static void main(String[] args) {
        //被代理类
        ScanService scanService = new ScanServiceImpl();
       //能生成动态代理功能的类 先创建出来
        MyJdkProxy myJdkProxy = new MyJdkProxy(scanService);

        ScanService instance = (ScanService)myJdkProxy.getInstance();
        instance.scan();
        //System.out.println(instance);
    }

细节:

package cn.cdqf.proxy;

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

/**
 * 步骤
 * 1.实现InvocationHandler接口
 */
public class MyJdkProxy<T> implements InvocationHandler {
    //Object object;
    T object;
    //object:被代理的类
    public MyJdkProxy(T  object){
        this.object = object;
    }
    /**
     * 增强一个方法:在方法前,方法正常结束后,方法抛异常后,方法无论抛不抛异常后
     * @param proxy
     * @param method:代表现在正在调用的方法
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //增强的逻辑
        System.out.println("方法调用前增强逻辑。。。。");
        //增强不增强,原来的逻辑不能变,原方法该调用还得调用  调用的原来scan
        try {
            Object invoke = method.invoke(object, args);
            System.out.println("正常结束方法增强的逻辑");
            return invoke;//方法原来的返回值
        }catch (Exception e){
            System.out.println("异常结束后执行了逻辑");
        }finally {
            System.out.println("不管有没有异常都执行的逻辑");
        }
        System.out.println("方法调用后增强逻辑。。。。");
         return null;
    }
    //把被代理类给我了 我要调用一个方法去生成代理类
    public T getInstance(){
        //proxy是jdk提供的代理类,生成代理类的方法
        //因为要求方法名相同:jdk选择了接口
        /**
         * 类加载:加载功能
         * 被代理类实现的接口:为了统一方法名
         * 代理的功能,要如何增强,大家都乱写jdk不知道写在哪里的,jdk就要求必须传一个实现了
         * InvocationHandler的类,然后把增强逻辑写在invoke方法中
         *
         * jdk生成的代理类 会跟被代理类实现同一个接口
         */
        return (T)Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces()
        ,this);
    }
}

cglib动态代理

1.asm字节码技术实现,jdk内部实现

2.asm生成的代理类是被代理类的子类,jdk生成是兄弟类,跟被代理类实现同一个接口

 <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
package cn.cdqf.proxy;

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

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    //被代理类
    private Object object;
    public CglibProxy(Object object){
        this.object = object;
    }
    public Object getObject(){
        Enhancer enhancer = new Enhancer();
        //被代理类的子类 所有被代理类是代理类的父类
        enhancer.setSuperclass(object.getClass());
        //指定怎么增强
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("方法执行前加逻辑");
        //调用本来的方法
        Object invoke = method.invoke(object, args);
        System.out.println("方法执行后加逻辑");
        return invoke;
    }
}

 		//被代理类
        ScanService scanService = new ScanServiceImpl();
        CglibProxy cglibProxy = new CglibProxy(scanService);
        ScanService scanService1 =(ScanService)cglibProxy.getObject();
        scanService1.scan();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值