动态代理的原理

Posted 杨斌并

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理的原理相关的知识,希望对你有一定的参考价值。

Proxy.newProxyInstance 代理需要代理一个接口或者接口的实现类,但是必须有接口

代理一个接口
interface IPerson 
    fun eat(eat: String);
    fun read(content: String): String;


     val p = Proxy.newProxyInstance(
                classLoader,
                arrayOf(IPerson::class.java),
                InvocationHandler  proxy, method, args ->
                    if ("eat" == method.name) 
                        println("调用了eat $args[0]")
                     else if ("read" == method.name) 
                        println("调用了read $args[0]")
                        return@InvocationHandler "红楼梦"
                    
                    null
                ) as IPerson

            p.eat("茶")
            val read = p.read("西游记")
            println(read)
代理一个实现了一个接口的实体类
public interface Person 
    String read();
    void eat();


public class Teacher implements Person
    @Override
    public String read() 
        System.out.println("我读书了");
        return "小学课本";
    

    @Override
    public void eat() 
        System.out.println("eat 学校套餐");
    


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

public class PersonHandler<T> implements InvocationHandler 
    private T t;
    PersonHandler(T t)
        this.t = t;
    


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
        System.out.println(method.getName());
        if ("eat".equals(method.getName()))
            System.out.println("调用了eat前");
            Object invoke = method.invoke(t, args);
            System.out.println("调用了eat后");
            return invoke;
        else if ("read".equals(method.getName()))
            System.out.println("调用了read前");
            Object invoke = method.invoke(t, args);
            System.out.println("调用了read后");
            return invoke;
        
        return method.invoke(t, args);
    



public void invoke()
       val teacher = Teacher()
            val p = Proxy.newProxyInstance(
                Teacher::class.java.classLoader,
                arrayOf(Person::class.java),
                PersonHandler(teacher)
            ) as Person
            p.eat()
            p.read()

CGLIB代理 可以代理一个实体类不需要接口

public class UserService 
    
    public void getName()
        System.out.println("张三!");
    


public class ProxyFactory<T> implements MethodInterceptor 

    private T target;

    public ProxyFactory(T target) 
        this.target = target;
    

    // 创建代理对象

    public Object getProxyInstance() 

        // 1.cglib工具类
        Enhancer en = new Enhancer();
        // 2.设置父类
        en.setSuperclass(this.target.getClass());
        // 3.设置回调函数
        en.setCallback(this);

        return en.create();
    

   //拦截方法
    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy methodProxy) throws Throwable 
        System.out.println("开始事务...");

        // 执行目标对象的方法
        Object result = method.invoke(target, args);

        System.out.println("提交事务...");
        return result;
    

以上是关于动态代理的原理的主要内容,如果未能解决你的问题,请参考以下文章

X-Powered-By中的Express在哪个地方能改呢

隐藏响应的server,X-Powered-By

DouPHP去除Powered by DouPHP版权的方法

Sysdig and Falco now powered by eBPF

X-Powered-By: ASP.NET是干啥用的

怎么去掉powered by ecshop