动态代理
代理:辅助对象处理一些操作,为对象的行为做代理(明星的经纪人)。
动态代理调用方法的流程
- 走向代理
- 代理为方法额外做一些辅助工作
- 触发真正的对象方法执行
- 回到代理中,由代理返回结果给方法调用者
实现动态代理的步骤
- 必须定义接口
- 被代理对象必须实现接口
- 使用Proxy类提供的newProxyInstance方法,得到对象的代理对象
动态代理例子
//被代理对象的技能接口
public interface Skill {
void sing();
void dance();
}
//明星类(实现Skill接口)
public class Star implements Skill{
String name;
public Star(String name) {
this.name = name;
}
@Override
public void sing() {
System.out.println(name + "开始唱《爱你》");
}
@Override
public void dance() {
System.out.println(name + "开始跳宅舞");
}
}
//明星的代理人类
public class StarAgent {
public static Skill getProxy(Star obj) {
//3.用传入的被代理对象构造代理对象,并以接口类型返回
return (Skill) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
//method:传入的方法 args:传入的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//4.额外的操作(动态代理的目的)
System.out.println("收首付款");
//5.真正调用被代理对象的方法
Object result = method.invoke(obj,args);
System.out.println("收尾付款");
return result;
}
});
}
}
//测试类
public class Test {
public static void main(String[] args) {
//1.实例化被代理的对象
Star s1 = new Star("杨超越");
//2.将被代理对象传入代理类方法
Skill s2 = StarAgent.getProxy(s1);
//6.实际是通过代理对象调用的方法
s2.sing();
s2.dance();
}
}
输出结果:
收首付款
杨超越开始唱《爱你》
收尾付款
收首付款
杨超越开始跳宅舞
收尾付款
动态代理的作用
-
在不改变方法源码的情况下,增强方法功能,提高复用性
-
提高开发效率和可扩展性
-
可为被代理对象所有方法做代理
-
可以为任意接口的实现类对象做代理
-
public class StarAgent { //将接口类型改为T(任意类型) public static <T> T getProxy(T obj) { return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { @Override //method:传入的方法 args:传入的参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("收首付款"); Object result = method.invoke(obj,args); System.out.println("收尾付款"); return result; } }); } }