- 什么动态代理模式:动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时 根据需要动态创建目标类的代理对象。
- 实现动态代理模式相关的api:
- Proxy类:专门完成代理的操作类,是所有动态代理类的父类。通过此类为一 个或多个接口动态地生成实现类。
- 提供用于创建动态代理类和动态代理对象的静态方法:
- static Class getProxyClass(ClassLoader loader, Class... interfaces) 创建 一个动态代理类所对应的Class对象
- static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 直接创建一个动态代理对象
- newProxyInstance方法中的参数1loader传入被代理类的类加载器,参数2interfaces[]传入被代理类的实现接口(可能实现多个接口),参数3h传入InvocationHandler接口的实现类对象,也就是说需要我们创建自定义类去实现InvocationHandler接口,并重写其中的
Object invoke(Object proxy, Method method, Object[] args):其中的重写的方法体就是增强的逻辑,同时是代理类调用的方法,其中间接的调用被代理原来实现接口所重写的方法
实现动态代理,需要解决的问题:
- 问题1:如何根据加载到内存中的被代理类,去动态的创建代理类及其对象
- 问题2:当通过代理类调用方法a时,如何动态的调用被代理类中的同名方法a
具体的代码实现:
package com.atguigu.java2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class StaticProxyTest {
public static void main(String[] args) {
AKun aKun = new AKun();
Person proxyInstance = (Person) ProxyFactory.getProxyInstance(aKun);
proxyInstance.show();
}
}
//提供一个接口
interface Person {
//提供一个抽象方法show
void show();
}
//提供被代理类
class AKun implements Person {
@Override
public void show() {
System.out.println("阿坤会才艺表演");
}
}
//提供一个动态代理工厂,用于动态生成代理类
class ProxyFactory {
//提供一个静态方法,用于返回代理类对象
public static Object getProxyInstance(Object obj) {
ClassLoader classLoader = obj.getClass().getClassLoader();
Class<?>[] interfaces = obj.getClass().getInterfaces();
MyInvocationHandler handler = new MyInvocationHandler(obj);
return Proxy.newProxyInstance(classLoader, interfaces, handler);
}
}
//提供一个InvocationHandler接口的实现类
class MyInvocationHandler implements InvocationHandler {
private Object obj;//需要使用被代理类对象进行赋值
public MyInvocationHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法体即为具体代理的内容,即增强的逻辑
Object invoke = method.invoke(obj, args);
System.out.println("阿坤还会唱歌");
System.out.println("阿坤还会跳舞");
System.out.println("阿坤还会rap");
System.out.println("阿坤还会打篮球");
return invoke;
}
}