java代理模式

今天学习了代理模式,心血来潮便做做笔记

代理模式有两种:静态代理,动态代理

含义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

例如生活中的汽车中介,客户觉得自己去车店看车太辛苦了,于是找到了中介,中介这里什么车都有,但是价钱会更贵一点。

为什么要使用代理模式?

1、遵循开闭原则,方便扩展。代理可以做一些额外的事情

2、遵循依赖倒置,降低类之间的耦合

缺点:每次都要创建代理类实现接口,所以就有了动态代理

静态代理:

 //买汽车接口

package com.mode.daili;

public interface BuyCar {
    void buyCar();  //买汽车
}

 //客户类

package com.mode.daili;

public class Customer implements BuyCar {

    @Override
    public void buyCar() {
        System.out.println("我要买车");
    }
}

 //代理

package com.mode.daili;

public class Daili implements BuyCar {
    private Customer customer;

    public Daili(Customer customer) {
        this.customer = customer;
    }

    @Override
    public void buyCar() {
        System.out.println("请跟我先看车"); //买车前做的事
        customer.buyCar();
        System.out.println("请支付Money"); //买车后做的事

    }
}

 //测试

package com.mode.daili;

public class Main {
    public static void main(String[] args) {
        BuyCar daili = new Daili(new Customer());
        daili.buyCar();
    }
}

结果

动态代理:

1、jdk动态代理

2、cglib动态代理

创建jdk代理类

package com.mode.proxy.dongtai.homework1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//jdk代理类
public class MyInvocationHandlerJDK implements InvocationHandler {
    private Object target;

    public MyInvocationHandlerJDK(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK代理类");//可以在被代理类方法使用前后做其它操作
        Object obj = method.invoke(target, args);//使用方法
        return obj;
    }
}
package com.mode.proxy.dongtai.homework1;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
//创建cglib代理类
public class MyInvocationHandlerCglib implements MethodInterceptor {
    private Object target;

    public MyInvocationHandlerCglib(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Cglib代理此方法");//可以在被代理类方法使用前后做其它操作
        Object result = methodProxy.invoke(target,objects); //使用方法
        return result;
    }
}

//工具类

package com.mode.proxy.dongtai.homework1;

import net.sf.cglib.proxy.Enhancer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 工具类
 */
public class ProxyGenerator {
    //把对象代理的方法,如果对象有实现接口,就使用jdk代理,否则Cglib代理
    public Object generate(Object target){
        Class<?>[] interfaces = target.getClass().getInterfaces();
        if(interfaces.length > 0){
            return generateJDK(target);
        }else {
            return generateCglib(target);
        }
    }
    //Cglib代理方法
    private Object generateCglib(Object target) {
        Enhancer enhancer = new Enhancer();
        //setSuperclass:设置被代理类的父类
        //setCallback:指定谁代理
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new MyInvocationHandlerCglib(target));
        return enhancer.create();//创建被代理后的对象并返回
    }
    //jdk代理方法
    private Object generateJDK(Object target){
        //创建代理类对象
        InvocationHandler handler = new MyInvocationHandlerJDK(target);
        //Proxy.newProxyInstance()
        //第一个参数:被代理类的类加载对象
        //第二个参数:被代理类的所有接口
        //第三个参数:指定谁代理
        Object obj = Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                handler
        );
        return obj; //返回被代理后的对象
    }
}

测试类

package com.mode.proxy.dongtai.homework1;

public class Main {
    public static void main(String[] args) {
        ProxyGenerator proxy = new ProxyGenerator();
        Book book = new Book();
        Book generate = (Book) proxy.generate(book);
        generate.printBook();
    }
}

jdk代理和cglib代理的区别

jdk代理:只能代理实现了接口的类的接口方法,不需要导入jar包;

cglib代理:可以代理没有实现接口的类,但需要导入jar包: asm-7.1    cglib-3.3.0

可自行去这里下:https://mvnrepository.com/

以上方法均已测试过,不足之处,多多见谅

原文地址:https://www.cnblogs.com/liweixml/p/11509413.html