对动态代理模式的理解

直接上代码

Subject接口

package cn.lichenyang.dao;

public interface Subject {
	
	   public void rent();
	    
	   public void hello(String str);
}

RealSubject,需要实现Subjct,实现自己的功能

package cn.lichenyang.dao.impl;

import cn.lichenyang.dao.Subject;

public class RealSubject implements Subject{

	@Override
	public void rent() {
		System.out.println("rent");
	}

	@Override
	public void hello(String str) {
		System.out.println("hello:"+str);
	}

}

DynamicProxy类,需要实现InvocationHandler接口

package cn.lichenyang.proxy;

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

//实现了InvocationHandler接口需要实现invoke方法
public class DynamicProxy implements InvocationHandler {

    // 这个就是我们要代理的真实对象
    private Object subject;
    
    //    构造方法,给我们要代理的真实对象赋初值
    public DynamicProxy(Object subject)
    {
        this.subject = subject;
    }
	
    
    //arg0:      指代我们所代理的那个  真实对象,和上面的subject是一个东西,不要Object subject,会重名
    //method:  指代的是我们所要调用  真实对象的某个方法的Method对象
    //args:    指代的是调用         真实对象某个方法时接受的参数
	@Override
	public Object invoke(Object arg0, Method method, Object[] args) throws Throwable {
		//在代理真实对象前我们可以添加一些自己的操作
        System.out.println("before rent house");
        
        
        //因为Object是运行过程创建的,不是真实存在的,所以输出会报错
        //需要明白的是,subject和arg0是一个东西就行了
//        System.err.println("subject" + subject);
//        System.err.println("arg0"+arg0);
        
        System.err.println("Method:" + method);
        System.err.println("args:" + args);//可以args[0]来查看具体的参数
        
        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        //invoke方法执行时需要知道方法所在的对象(实例),这个实例通过最上方的声明得到(就相当于是那个类中的方法需要被代理)
        //subject是真是对象,args是真是对象中的接口的方法所需要的参数
        method.invoke(subject, args);
        
        //在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("after rent house");
        
        /*
         * 解释:这个返回值写null就行了,对整个代理对象没有影响
         */
        return null;
		
	}

}

测试类:

package cn.lichenyang.test;

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

import cn.lichenyang.dao.Subject;
import cn.lichenyang.dao.impl.RealSubject;
import cn.lichenyang.proxy.DynamicProxy;

public class Client {

	public static void main(String[] args) {
		
	//通过多态,创建一个我们要代理的真实对象
        Subject realSubject = new RealSubject();

        //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
        InvocationHandler handler = new DynamicProxy(realSubject);

        /*
         * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
         * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
         * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
         * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
         */
        Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
                .getClass().getInterfaces(), handler);
        
        //调用这个方法的时候,进入代理对象中的proxy方法
        subject.hello("world");    //使用这个方法,args有值(world),使用下面的就没有值
//        subject.rent();
	}
}

动态代理和静态代理的区别:动态代理不用自己写代理类,静态代理需要自己写代理类

可以横向抽取重复的代码,然后放到invoke方法中,在main方法中调用的时候,就会自动加载重复的代码了

动态代码一定有接口,一定有接口实现类

猜你喜欢

转载自blog.csdn.net/qq_37385585/article/details/80897922