文章目录
一、动态代理
- 动态代理:客户通过代理类来调用其他对象的方法。可以在程序运行时根据需要动态创建被代理类的代理对象。
另外介绍–静态代理:代理类和被代理类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样程序开发中必然产生过多的代理。最好可以通过一个代理类完成全部的代理功能。
1.1动态代理的步骤即代码
-
创建一个实现接口InvocationHandler的类,它必须实现invoke方法,以完成代理的具体操作。
-
创建被代理的类以及接口
-
通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 创建一个Subject接口代理
-
通过Subject代理调用RealSubject实现类(即被代理对象调用自己的方法)的方法
-
以上步骤的代码实现
1. 创建一个实现接口InvocationHandler的类
package ProxyDemo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理类
* @author lby
*
*/
public class ProxyDemo implements InvocationHandler {
Object obj;//被代理的对象
public ProxyDemo(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"方法开始执行");
Object result = method.invoke(this.obj,args);//执行的是指定代理对象的指定的方法
System.out.println(method.getName()+ "方法执行结束");
return result;
}
}
2. 创建被代理的类以及接口
package ProxyDemo;
public interface ITestDemo {
void test1();
void test2();
}
package ProxyDemo;
public class ITestDemoImpl implements ITestDemo {
@Override
public void test1() {
System.out.println("执行了 test1 方法");
}
@Override
public void test2() {
System.out.println("执行了 test2 方法");
}
}
3. 通过Proxy的静态方法**newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)** 创建一个Subject接口代理
4. 通过Subject代理调用RealSubject实现类(即被代理对象调用自己的方法)的方法
package ProxyDemo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
ITestDemo iTestDemo = new ITestDemoImpl();
/**
* 注意:如果一个对象想要通过Proxy.newProxyInstance方法被代理,
* 那么这个对象的类一定要有相应的接口
* 就像本类中的ITestDemo接口和实现类TestDemoImpl
*/
iTestDemo.test1();
iTestDemo.test2();
System.out.println("======================");
/**
* 需求:
* 在执行test1和test2方法时需要加入一些东西
* 在执行方法前打印test1或test2开始执行
* 在执行方法后打印test1或test2执行完毕
* 打印的方法名要和当时调用方法保存一致
*/
InvocationHandler invocationHandler = new ProxyDemo(iTestDemo);
/**
* Proxy.newProxyInstance(ClassLoader, interfaces, h)
* 参数1是代理对象的类加载器
* 参数2是被代理的对象的接口
* 参数3是代理对象
*
* 返回的值就成功被代理后对象,返回的是Object类型,需要根据当时的情况去转换类型
*/
ITestDemo iTestDemo1 = (ITestDemo) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(),
iTestDemo.getClass().getInterfaces(),invocationHandler);
iTestDemo1.test1();
iTestDemo1.test2();
}
}
输出
执行了 test1 方法
执行了 test2 方法
======================
test1方法开始执行
执行了 test1 方法
test1方法执行结束
test2方法开始执行
执行了 test2 方法
test2方法执行结束