Java 代理模式
代理的作用
想象一个场景。我们一个项目已经开发完成,并且部署了很长一段时间。但是突然需要功能更新,那必然涉及到代码的修改。但是我们也知道稍微不注意的修改,出错了,整个项目就很爆炸了。
所以为了不破坏已经完善封装的代码。我们又想要给我们的某些功能做一些增强。我们就可以使用代理,建立一个代理类。
静态代理
静态代理的基本模式
-
定义一个接口
interface Animal{ public void eat(); }
-
写一个类实现接口
class Dog implements Animal{ @Override public void eat() { System.out.println("狗在吃骨头"); } }
-
写一个代理类代理
class DogProxy implements Animal{ private Dog dog=new Dog(); @Override public void eat() { System.out.println("静态代理类前置内容");//在这可以做一些逻辑 dog.eat(); System.out.println("静态代理类后置内容"); } }
-
使用
public class StaticProxyDemo { public static void main(String[] args) { Animal dog=new DogProxy(); dog.eat(); } }
静态代理的用法
假设一个场景,我们开发了一系列手机的通话功能,然后我们发布出去了。没过两天,用户提问题了,怎么我输错号码都不带提示的啊。不行了,产品经理跑来让我们改需求了。我们加班一晚上,给每个手机的通话功能加上电话号码验证的逻辑。于是有了以下结果。
//原来代码的样子
interface Phone{
public void callPhone(String phoneNum);
}
class ApplePhone implements Phone{
@Override
public void callPhone(String phoneNum) {
System.out.println("ApplePhone calling");
}
}
class MIPhone implements Phone{
@Override
public void callPhone(String phoneNum) {
System.out.println("MIPhone calling");
}
}
class HuaWeiPhone implements Phone{
@Override
public void callPhone(String phoneNum) {
System.out.println("HuaWeiPhone calling");
}
}
//更改后
interface Phone{
public void callPhone(String phoneNum);
}
class ApplePhone implements Phone{
@Override
public void callPhone(String phoneNum) {
/*
* 因为需求加的验证电话号码的逻辑
* */
System.out.println("ApplePhone calling");
}
}
class MIPhone implements Phone{
@Override
public void callPhone(String phoneNum) {
/*
* 因为需求加的验证电话号码的逻辑
* */
System.out.println("MIPhone calling");
}
}
class HuaWeiPhone implements Phone{
@Override
public void callPhone(String phoneNum) {
/*
* 因为需求加的验证电话号码的逻辑
* */
System.out.println("HuaWeiPhone calling");
}
}
我们先不讨论这些逻辑可以抽出来单独写一个方法,这不是重点。重要的是,我们在原来写好的代码里面加了代码,已经不能保证一定不会破坏整个环境。而且不保证会不会更大的更改。
比如之前是void callPhone。没准修改以后是Boolean callPhone(根据这个方法的运行逻辑处理以后项目的运行逻辑)。这样如果项目足够紧凑,那么可能就是一次重构。
而有了代理以后,我们可以这样做。
class PhoneProxy implements Phone {
private Phone phoneObject;
PhoneProxy(Phone phone) {
this.phone = phone;
}
@Override
public void callPhone(String phoneNum) {
judgePhoneNum(phoneNum);//新增逻辑
phone.callPhone(phoneNum);
}
}
动态代理
这里说的是Cglib的动态代理,需要相应的jar包,而cglib以来asm。所以两个包都要导。
package prox;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
class BookFacadeImpl{//没有接口,因为cglib就是对普通类进行增强
public void addBook(){
System.out.println("增加图书的方法。。。");
}
}
//使用Cglib代理
class BookFacadeCglib implements MethodInterceptor{
private Object target;
/**
* 创建代理对象
* @param target
* @return
*/
public Object getInstance(Object target){
this.target=target;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects,MethodProxy proxy) throws Throwable {
System.out.println("方法执行前逻辑");
proxy.invokeSuper(o,objects);
System.out.println("方法执行后逻辑");
return null;
}
}
public class DynamicProxyDemo {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl());
bookCglib.addBook();
}
}