引言
首先,代理模式分为两个角色,一个代理的公司,一个被代理的角色
好处:不言而喻,被代理的角色什么事都不用做,只用调用一下公司的方法,也就是服从公司的安排就行。
代理分为静态代理和动态代理
先让我们看看静态代理
静态代理
代码固定死了,而且每多一个人要来公司请求代理,都要重新创建一个人和公司。
不灵活,代码量大
Rent.java
public interface Rent {
public void rent();
}
RentImpl.java
public class RentImpl implements Rent {
@Override
public void rent() {
// TODO 自动生成的方法存根
System.out.println("房东要租房子");
}
}
Company.java
public class Company {
private Rent r;
public Company(Rent r) {
this.r = r;
}
public void see() {
log("代理");
System.out.println("带人去看房子");
}
public void money() {
log("代理");
System.out.println("该收钱了");
}
public void log(String msg) {
System.out.println(msg);
}
public void proxy() {
r.rent();
see();
money();
}
}
Test.java
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
RentImpl rent=new RentImpl();
Company company=new Company(rent);
company.proxy();
}
}
//输出结果:
房东要租房子
代理
带人去看房子
代理
该收钱了
不言而喻,我多一个要代理的人,比如他要求不一样,那我就需要重新改代码,所以静态代理的弊端由此可见
动态代理
- 代理对象(我)+代理类(婚庆公司)代理对象
- 有一个接口和实现类而代理类主要由Proxy和invocationHandler工具类中: 传一个target目标代理对象的实现类。
- 然后第二步生成得到代理类 利用类加载器,代理对象接口,invocationHandler
- 最后一步就是实现invocationHandler的方法invoke利用反射机制直接返回method的invoke(代理对象,args)
所以客户想要用的话,直接传入自己的对象,去改变代理对象,然后执行第二步动态生成代理类并强转,然后这个对象就能调用方法了
ProxyInvocationHandler.java
public class ProxyInvocationHandler 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);
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable {
// TODO 自动生成的方法存根
Object result=method.invoke(target, arg2);
return result;
}
}
Test.java
这里用的Rent和实现类和静态代理的那个代码一样,拿过来复用
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//真实角色 房东
RentImpl rent=new RentImpl();
//代理角色 公司
ProxyInvocationHandler pih=new ProxyInvocationHandler();
pih.setTarget(rent);//设置要代理的对象,比如这是房东要被代理
//动态生成代理类
Rent proxy=(Rent)pih.getProxy();
proxy.rent();
}
}
你会发现,动态代理为什么我能复用那个房东类,我也可以新建一个代理角色,比如租车的类等等,你会发现,测试类中最重要的是你只需要传进去一个被代理的角色接口和实现类,
无论是谁来代理都可以用这个动态生成代理类,然后达到实现被代理的人要干的事
所以动态代理非常重要,在Spring中的aop就是如此,你只需要传一个功能就可以切面进Spring