动态代理:
代理:本来应该自己做的事情,却请了别人来做,被请来的人就是代理对象
例如:
动态代理:在程序运行的过程中产生的这个对象
在代理的过程中,可以在本类基础上添加新的功能,使其功能更强大
注意,代理对象代理(执行)的是被代理对象的方法。即本来就是被代理对象拥有的方法,只是原来由被代理对象执行,现在换成了代理对象去执行,但是这个方法本来就是被代理者拥有的方法。
jdk提供的代理只能针对接口做代理,我们有更强大的代理cglib
java中的代理
java在java.lang.reflect包下给我们提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口我们就可以生成动态代理对象。
使用方式
再次强调,java提供的动态代理只能针对接口做代理
1.定义接口
/**
* 将要被代理的接口
* eat为有参,无返回值的示例方法
* sleep为无参,有返回值的示例方法
*/
public interface Aniamal {
void eat(String food);
boolean sleep();
}
2.定义接口的实现类
/**
* 接口的具体实现类
*
*/
public class Person implements Aniamal {
private static final String TAG = "Person";
@Override
public void eat(String food) {
Log.d(TAG, "eat: 吃了"+food);
}
@Override
public boolean sleep() {
Log.d(TAG, "sleep: 睡的不错");
return true;
}
}
3.实现InvocationHandler类
/**
* 定义InvocationHandler的实现类
*
*/
public class PersonInvocationHandler implements InvocationHandler {
private Aniamal aniamal;// 被代理对象
//被代理对象要构造传参进来
public PersonInvocationHandler(Aniamal aniamal) {
this.aniamal = aniamal;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//我们可以在方法执行前或者执行之后加入自己的逻辑
//proxy为代理对象
//这里的method就是将来我们调用的method
//args就是我们传进来的参数
//result是我们调用的method的返回值
Object result = method.invoke(aniamal, args);
return result;
}
}
4.使用
//创建被代理对象
Person person = new Person();
//创建InvocationHandler对象
PersonInvocationHandler handler = new PersonInvocationHandler(person);
//创建代理对象,将代理对象转换成被代理对象接口类型
//创建方式一
Aniamal proxyInstance =(Aniamal) Proxy.newProxyInstance(person.getClass().getClassLoader(),
person.getClass().getInterfaces(), handler);
//创建方式二
Aniamal proxyInstance =(Aniamal) Proxy.newProxyInstance(Aniamal.class.getClassLoader(),
Person.class.getInterfaces(), handler);
//代理对象执行被代理对象的方法
proxyInstance.eat("羊蝎子");
boolean sleep = proxyInstance.sleep();
下面我们看PersonInvocationHandler中的逻辑
修改委托类的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//修改委托类的方法
String name = method.getName();
//如果发现让我吃羊蝎子,就强制改成吃烤鸭
if (name.equals("eat") && args[0].equals("羊蝎子")) {
return method.invoke(aniamal,"烤鸭");
}
return method.invoke(aniamal,args);
}
过滤委托类的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//过滤委托类的方法
String name = method.getName();
//如果发现要调用睡觉的方法,那么就不执行
if (name.equals("sleep")) {
return false;
}
return method.invoke(aniamal,args);
}
修改方法的返回值
这个更容易,只要return自己想要的任何值就可以类
动态代理作用
1、不需要得到对应委托类的对象
2、获取委托类的方法中的参数
3、通过代理类对象,对委托类的方法进行过滤(修改)等
4、修改委托类方法的返回值