1.概念
动态代理是设计模式中代理模式中的一种,它可以实现在不改变目标对象方法的情况下对方法进行增强。
2.组成
代理对象:内存中的一个对象,对被代理对象进行增强;
被代理对象:真实的对象;
3.使用条件
使用动态代理要有接口的存在,而且代理对象和被代理对象必须实现相同的接口;
4.使用
- Proxy.newProxyInstance();
- 该方法中需要传递的3个参数:
1.类加载器:和被代理对象使用相同的类加载器
2.接口类型的Class数组(一个数组,数组内的元素为接口的Class类型):和被代理对象使用相同接口
3.代理规则:完成代理增强的功能
- 该方法中需要传递的3个参数:
5.小案例
1.创建一个Sporter类:
public class Sporter{
public void eat(String name){
System.out.println("运动员吃:"+name);
}
public void sport(){
System.out.println("运动员跑步");
}
}
2.创建一个Test类:
public class Test {
public static void main(String[] args) {
Sporter sporter = new Sporter();
sporter.eat("米饭");//输出“运动员吃:米饭”
sporter.sport();//输出“运动员跑步”
}
}
3.需求:在不改动Sport类中任何代码的情况下,通过sport方法输出:运动员游泳。可以使用动态代理的方式来实现:
- 创建一个SporterInterface接口:
public interface SporterInterface{
public abstract void eat(String name);
public abstract void sport();
}
- 让Sporter类来实现接口:
public class Sporter implements SporterInterface{
//运动员对象为被代理对象
public void eat(String name){
System.out.println("运动员吃:"+name);
}
public void sport(){
System.out.println("运动员跑步");
}
}
- 在Test类中使用动态代理:
public class Test {
public static void main(String[] args) {
Sporter sporter = new Sporter();
/*可以使用动态代理来实现需求;
# 使用动态代理的要求:使用动态代理要有接口的存在,而且代理对象和被代理对象必须实现相同的接口;
# 实现:Proxy.newProxyInstance();
该方法中需要传递的3个参数:
1.类加载器:和被代理对象使用相同的类加载器
2.接口类型的Class数组(一个数组,数组内的元素为接口的Class类型):和被代理对象使用相同接口
3.代理规则:完成代理增强的功能
*/
SporterInterface proxySpo = (SporterInterface) Proxy.newProxyInstance(sporter.getClass().getClassLoader(),
new Class[]{SporterInterface.class},
new InvocationHandler() {
/* 执行Sporter类中所有方法都会经过invoke方法;
* 1.Method 参数:封装被代理对象中的方法;
* 2.Object[] 参数:Object类型数组,封装执行Method方法时所需传递的参数;
* 在invoke方法中判断被代理对象(Sporter)中的方法:如果是sport方法则对其增强;如果不是则执行Sporter对象原有的功能;
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("sport")) {
System.out.println("运动员游泳");
return null;
} else {
return method.invoke(sporter, args);
}
}
});
//测试代理对象功能
proxySpo.eat("米饭");
proxySpo.sport();
}
}