实现代理的几种方法

代理模式是设计模式结构型中的其中一种
实现代理功能有静态代理,动态代理,Cglib的几种方式
如果没有概念,接下来一一分别代码简单实现,看看主要的不同,写完基本能有个基本认知

代理即 两个类之间不直接产生关系,而由中间设置的代理类来实现交互。


先做一个例子

1.单纯恰饭

学生吃饭,(没得办法只会来这些吃饭简单例子)
老师吃饭。
分别实现Person接口
Person:

public interface Person {
    
    
    void eat();
}

Student:

public class Student  implements Person{
    
    
	@Override
	public void eat() {
    
    
        System.out.println("Student eating");
    }
}

Teacher:


public class Teacher  implements Person{
    
    
	@Override
    public void eat() {
    
    
        System.out.println("Teachers eating");
    }
}

2.吃饭前运动一下,吃饭后读一下书

Student:

public class Student  implements Person{
    
    
	@Override
	public void eat() {
    
    
		System.out.println("play basketball");
        System.out.println("Student eating");
        System.out.println("read 《五年高考三年模拟》");
    }
}

Teacher:

public class Teacher  implements Person{
    
    
	@Override
    public void eat() {
    
    
    	System.out.println("play basketball");
        System.out.println("Teachers eating");
        System.out.println("read 《五年高考三年模拟》");
    }
}

当然老视也得看五三
那这样的话我们没增加一个功能的话都必须老视学生一起改,很繁琐,七八个十几个person实现类、
有没有简单的一劳永逸的简单三五行实现的呢,这个还真的有
那就是 代理了,


先说一个 静态代理

一、静态代理

静态代理必须要实现 统一的接口,重写方法,所不同的是传入不同的实现类,就会不同的实现,
最后如果再对 吃前后进行增强减弱都可以在代理类中进行更改,student和teacher都不需要再动了

ProxyPerson:

public class ProxyPerson implements Person{
    
    

    private Person person = null;

    public ProxyPerson(Person person1) {
    
    
        person = person1;
    }
	@Override
    void eatting() {
    
    
        System.out.println("washing clothes before eating");
        person.eat();
        System.out.println("run after eated");
    }
}

测试:

/**
     * 静态代理
     * 实现学生和老师的池
     * 改变代理类的同时不影响原生类
     */
    @Test
    public void smain() {
    
    
        ProxyPerson proxyPerson = new ProxyPerson(new Student());
        ProxyPerson proxyPerson2 = new ProxyPerson(new Teacher());
        proxyPerson.eatting();
        System.out.println("-------->>");
        proxyPerson2.eatting();
    }

二、动态代理

动态代理是jdk 自带的包,不需要额外导入
动态代理的必要条件是必须要实现相同的接口。
基本的实现就是通过反射得到 代理实现,将参数传入,invoke执行即可
动态代理需要实现 InvocationHandler 接口,重写 invoke() 方法

public class JDKProxyHandler implements InvocationHandler {
    
    

    private Object obj;

    public JDKProxyHandler(Object resut) {
    
    
        this.obj = resut;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    


        System.out.println("wash clothes before eat----");
        Object result = method.invoke(obj, args);
        System.out.println("run after ea8888t");

        return result;
    }


    /**
     * 获取代理 类对象
     *
     * @param <T>
     * @return
     */
    public <T> T getObj() {
    
    
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

}

测试方法

/**
     * JDK 自带的动态代理  必须实现接口
     * 主要是反射method.invoke()
     */
    @Test
    public void getProxy() {
    
    
        JDKProxyHandler studentP = new JDKProxyHandler(new Student());
        JDKProxyHandler teacherP = new JDKProxyHandler(new Teacher());
        Person s = studentP.getObj();
        Person t = teacherP.getObj();
        s.eat();
        System.out.println("------------========》》》");
        t.eat();
    }

三、Cglib 织入

JDK 的动态代理需要 实现相同的接口,有一定的局限性。
而为了应对这个问题,出现了新技术Cglib

CGLib(Code Generator Library)是一个强大的、高性能的代码生成库。底层使用了ASM(一个短小精悍的字节码操作框架)来操作字节码生成新的类

而需要使用需要额外导入三方的jar

         <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.10</version>
        </dependency>

实现 MethodInterceptor 接口具体的代码

public class CglibClass implements MethodInterceptor {
    
    


    // 单例模式获取实例
    private static CglibClass cglibClass = new CglibClass();

    public static CglibClass getInstance() {
    
    
        return cglibClass;
    }


    // 获取被代理的目标类
    public <T> T getProxy(Class<T> clazz) {
    
    
        return (T) Enhancer.create(clazz, this);
    }


    /**
     * 代理执行目标类方法
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
    

        System.out.println("read before eated");

        Object invoke = methodProxy.invokeSuper(o, objects);

        System.out.println("run after eated");

        return invoke;
    }

测试方法

 /**
     * cglib  代理目标类,并且在类中进行自定义增强
     */
    @Test
    public void getProxyIn() {
    
    
        Person proxy = CglibClass.getInstance().getProxy(Student.class);
        Person proxy2 = CglibClass.getInstance().getProxy(Teacher.class);
        proxy.eat();
        System.out.println("-=-=-=-=-=--=--=--=->>");
        proxy2.eat();
    }

Guess you like

Origin blog.csdn.net/weixin_41086086/article/details/102609842