学习任务:

视频学习

什么是动态代理

测试动态代理入门程序

静态代理是代理类在编写时需要实现目标对象的接口,这样就限制了代理对象的功能,比如下边的代理类对ScoreService进行代理:

package com.pbteach.javase.oop.proxy;

/**
 * 代理模式测试
 * @author 攀博课堂(www.pbteach.com)
 *
 */
public class ProxyService implements IScoreService  {
	//目标对象
	private IScoreService scoreService;
	//通过set方法将目标对象设置到代理对象中
	public void setScoreService(IScoreService scoreService) {
		this.scoreService = scoreService;
	}

	@Override
		public float inputScore(float... scoreList) {
			//这里统一捕获异常
			try {
				//在这里可以添加代码,比如记录日志
				System.out.println("执行前记录日志...");
				return scoreService.inputScore(scoreList);
			} catch (Exception e) {
				System.out.println("在代理类中统一捕获异常");
				e.printStackTrace();
			}
			return 0;
		}

	
}

系统中有大量的Service类,按照静态代理的模式 需要创建大量的代理类,所以比较累赘。

动态代理可以解决静态代理的问题,何为动态代理呢?

动态代理类是无需程序员编写,由JVM自动生成实现了指定接口的Class对象,该Class对象就是代理类的Class对象,指定什么样的接口则生成实现该接口的代理类,所以这个过程是动态的,所以叫动态代理类,动态 代理类的对象就是动态代理对象

动态代理对象由java.lang.reflect.Proxy来创建。

查看Api文档如下:

image-20200930171535880

上边的代码是两种方法,这里参考第二种,即使用newProxyInstance方法创建代理对象:

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

1、Class<?>[] interfaces

代理类实现的接口列表 。

代理类是针对目标类的代理,所以代理类需要实现目标类的所有接口,所以需要将目标类实现的所有接口拿到,通过class对象的getInterfaces()方法即可拿到。

2、ClassLoader loader

类加载器,用于生成代理类的Class对象,调用class对象的getClassLoader()方法可以获得。

3、InvocationHandler处理器

处理器,查看Api如下:

image-20200930172836475

从上边的解释可以知道,每个动态代理对象会关联一个处理器程序,当调用代理对象的方法时会调用处理器程序的invoke方法。

代理类与处理器程序之间的关系如下:

image-20210222185917162

动态代理入门程序代码如下:

package com.pbteach.javase.oop.proxy;

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


/**
 *  动态代理测试
 * @author 攀博课堂(www.pbteach.com)
 *
 */
public class ProxyDemo2  {
	
	//动态代理入门程序
	public static void test1() {
		
		//定义处理器对象
		InvocationHandler handler = new InvocationHandler() {

			//参数1:jvm生成的动态代理对象
			//参数2:调用的目标方法(也就是接口中的方法)
			//参数3:调用方法所传入的参数
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println(proxy.getClass());
				System.out.println(method);
				float[] scoreList = (float[]) args[0];
				System.out.println(scoreList[1]);
				return 0.0f;
			}
			
		};
		//生成代理对象
		
		IScoreService scoreService = (IScoreService) Proxy.newProxyInstance(IScoreService.class.getClassLoader(),
                new Class<?>[] { IScoreService.class },
                handler); 
		//调用代理对象的方法
		scoreService.inputScore(100);
		
	}
	
	public static void main(String[] args) {
		test1();
	}
	
}

输出:

class com.sun.proxy.$Proxy0
public abstract void com.pbteach.javase.oop.proxy.IScoreService.inputScore(float)
100.0

提问-攀博课堂
我要提问 不会就问,有效沟通
关注公众号,加入微信群交流提问。 攀博课堂官方公众号
问答列表,查看本知识点所有问题