代理
什么是代理?
代理就是通过一个中间组件将两个不同的两个模块联系起来,使得两个模块不必知道彼此的详细实现细则,和中间件类似。这里两个组件一般是只接口和接口的实现类。
代理的作用?
-
可以隐藏委托类(被代理的类)的实现;
-
可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。
静态代理
若代理类在程序运行前就已经存在,那么这种代理方式被成为静态代理,这种情况下的代理类通常都是我们在Java代码中定义的。 通常情况下,静态代理中的代理类和委托类会实现同一接口或是继承自相同的父类。
定义一个IUser接口 //接口 interface IUser{ void doSomething(); }
实现IUser接口
//实现类
class UserImpl implements IUser{
@Override
public void doSomething() {
System.out.println("实现类do something");
}
}
定义一个代理类,同样实现IUser里的接口
//静态代理类
class UserProxy implements IUser{
private UserImpl user = new UserImpl();
@Override
public void doSomething() {
System.out.println("静态代理do something(before)");
user.doSomething();
System.out.println("静态代理do something(after)");
}
}
和实现类UserImpl不同的是,UserProxy实现IUser接口时,实在原有UserImpl实现的基础上扩展了其功能:在doSomething的前后干了其他事情。
这样就实现了在不改变UserImpl的基础上对其扩展。(事实上继承UserImpl并重写其方法,并在重写方法中调用父类的方法也能达到同样的效果)
测试
public static void main(String[] args) {
UserProxy userProxy = new UserProxy();
//在不改变原实现类的情况下,对IUser进行扩展
userProxy.doSomething();
}
输出结果:
静态代理do something(before)
实现类do something
静态代理do something(after)
动态代理
静态代理需要实现接口或者重写父类的的方法,若接口中有100个方法,则会做大量的重复工作,例如:
//接口
interface IUser{
void doSomething();
void doSomething1();
...
void doSomething100();
}
//实现类
class UserImpl implements IUser{
@Override
public void doSomething() {
System.out.println("实现类do something ");
}
@Override
public void doSomething1() {
System.out.println("实现类do something 1");
}
...
@Override
public void doSomething100() {
System.out.println("实现类do something 100");
}
}
//静态代理类
class UserProxy implements IUser{
private UserImpl user = new UserImpl();
@Override
public void doSomething() {
System.out.println("静态代理do something(before)");
user.doSomething();
System.out.println("静态代理do something(after)");
}
@Override
public void doSomething1() {
System.out.println("静态代理do something1(before)");
user.doSomething();
System.out.println("静态代理do something1(after)");
}
...
@Override
public void doSomething100() {
System.out.println("静态代理do something100(before)");
user.doSomething();
System.out.println("静态代理do something100(after)");
}
}
这样就出现了大量的冗余代码。
所以为了解决这个问题就出现了动态代理。
代理类在程序运行时创建的代理方式被成为动态代理。也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。这个和拦截器很像,Spring的Aop就是使用了动态代理
定义一个IUser接口 //接口 interface IUser{ void doSomething(); }
实现IUser接口
//实现类
class UserImpl implements IUser{
@Override
public void doSomething() {
System.out.println("实现类do something");
}
}
定义一个动态代理类,必须实现InvocationHandler接口
//动态代理
class UserDynamicProxy implements InvocationHandler{
//被代理的对象
private Object tagrt;
//得到一个代理对象
public Object getInstance(Object tagrt){
this.tagrt = tagrt;
Class clazz = tagrt.getClass();
Object object = Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
return object;
}
//实现InvocationHandler中的invoke方法,在这个方法里边做扩展处理
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理do something(before)");
Object result = method.invoke(tagrt,args);//用了反射机制
System.out.println("动态代理do something(after)");
return result;
}
}
测试
public static void main(String[] args) {
UserDynamicProxy userDynamicProxy = new UserDynamicProxy();
IUser user = (IUser) userDynamicProxy.getInstance(new UserImpl());
user.doSomething();
}
输出结果
动态代理do something(before)
实现类do something
动态代理do something(after)