我们继续按着前面的节奏继续,上次是租房的例子进行的静态代理的方法,也就是多写了一个代理类来进行多余的操作,再加上经常的dao/service这种类型的纵向开发,在不修改源代码的情况下,我们多加了一个代理类来进行修改,但与之而来的缺点就是往往要有一个代理对象的时候我们就必须要多一个代理类,处理倒是较为繁琐,这时另一个概念就随之而来——动态代理。(这种动态的东西总是会和反射有点关系~~)
我们依然还是从租房的例子来说,现在仍是有要代理的对象rent接口和代理的真实角色Host
public interface Rent {
public void rent();
}
public class Host implements Rent {
public void rent() {
System.out.println("我要租我的房子,但是其他的处理事务我不想干");
}
}
那么如何用动态代理的方式来对这件租房的事情进行代理呢?这句话翻译一下就是如何动态的生成一个代理类而我们不用自己写(你可以理解为程序员的懒惰)。
实现动态代理的方法一般时两种,一种是接口实现,一种是类实现,我们这里就说接口的实现。
在接口实现中我们必须要认识的一个接口InvocationHandler和一个类Proxy。
InvocationHandler翻译过来就是调用处理程序,Proxy就是代理,所以既然说到接口肯定就要实现了呀,这个接口中有一个内置的方法。
public class Dong implements InvocationHandler {
//这个是处理代理实例的
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
return null;
}
}
从上面我们可以看到这个invoke的方法,它是用来处理代理实例的,就是那个Host,你可以看这个方法的参数,就是要处理某个类中的某个方法以及参数。
那么既然这个是专门用来处理那个代理对象的,说好的担架呢?不不不,是说好的自动生成代理类呢?人家也没有其他方法了呀,怎么办?没有枪没有炮…咱们就自己造嘛。
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
}
自己写一个方法,可见其返回对象是一个Object,这不就是一个类?具体怎么操作?这个时候我们的第二个类就来了。
Proxy犹如天降神兵,它后面那个newProxyInstance方法翻译过来都懂吧,生成一个新的代理实例,还等啥?干就完了,其中涉及的三个参数,类加载器,需要的接口还有这个调用代理程序的类,我们将需要的接口(就是需要代理的接口)设置为类的私有属性注入,我们都有了不是,默默写入。
private Rent rent;
public void setRent(Rent rent){
this.rent=rent;
}
最后那个invoke的方法
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Object result = method.invoke(rent, objects);
return result;
}
想要额外操作?可以,再这个类中添加想要的方法,放入invoke中
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
seeHouse();
Object result = method.invoke(rent, objects);
return result;
}
public void seeHouse(){
System.out.println("看房子");
}
就这了–
更精明一点就是把这个继承InvocationHandler改写成工具类,就是把原本的接口具体属性换成Object,举例子来说
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("add方法");
}
@Override
public void delete() {
System.out.println("delete方法");
}
@Override
public void update() {
System.out.println("update方法");
}
@Override
public void query() {
System.out.println("query方法");
}
}
正常开发流程,要加日志了现在。
public class Dong implements InvocationHandler {
private Object target;
public void setTarget(Object target){
this.target=target;
}
//这个是生成代理类的
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
//这个是处理代理实例的
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
log(method.getName());
Object result = method.invoke(target, objects);
return result;
}
public void log(String message){
System.out.println("执行了"+message+"方法");
}
}
测试
public static void main(String[] args) {
UserService userService=new UserServiceImpl();
Dong dong = new Dong();
dong.setTarget(userService);
UserService proxy = (UserService) dong.getProxy();
proxy.delete();
}