代理
通过不直接访问被代理对象的方式,而访问被代理对象的方法,这样的模式称为代理。
应用场景
- 在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情;
- 在使用RPC框架的时候,可以通过动态代理的方式来进行逻辑搭建,实现松耦合;
- SpringAOP 便是采用的动态代理的机制来完成的。
开闭原则
所谓开闭原则就是:对修改关闭,对扩展开放。java的动态代理便是基于这个原则之上的。
静态代理
在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成,这种代理称为静态代理。
代码示例
/**
* 顶层接口
* 游戏玩家
* @author smlf
*
*/
public interface Player {
void win();
}
/**
* 需要被代理的类
* 红方玩家
* @author smlf
*
*/
public class RedTeamPlayer implements Player {
@Override
public void win() {
System.out.println("I Win");
}
}
/**
* 静态代理类
* @author smlf
*
*/
public class ProxyRedTeamPlayer implements Player {
private RedTeamPlayer redTeamPlayer;
public ProxyRedTeamPlayer(RedTeamPlayer redTeamPlayer) {
this.redTeamPlayer = redTeamPlayer;
}
@Override
public void win() {
System.out.println("I'm ProxyRedTeamPlayer");
redTeamPlayer.win();
}
public RedTeamPlayer getRedTeamPlayer() {
return redTeamPlayer;
}
public void setRedTeamPlayer(RedTeamPlayer redTeamPlayer) {
this.redTeamPlayer = redTeamPlayer;
}
}
public class StaticProxyTest {
public static void main(String[] args) {
//redPlayer为被代理的对象,某些情况下 我们不希望修改已有的代码,我们采用代理来间接访问
RedTeamPlayer redPlayer = new RedTeamPlayer();
//创建代理类对象
ProxyRedTeamPlayer player = new ProxyRedTeamPlayer(redPlayer);
//调用代理类对象的方法
player.win();
}
}
输出结果
总的说来,静态代理是在代理类中引入了被代理类的对象,对原对象的方法进行了增强。
动态代理
在开发时不能确定代理类和被代理类,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制。
java.lang.reflect 包下提供了 Proxy 类和 InvocationHandler 接口,通过这个类和接口可以生成java动态代理类和动态代理对象。
Proxy提供了用于创建动态代理类和代理对象的静态方法:
- static Class<?> getProxyClass(ClassLoader loader, Class<?>… interfaces):创建一个动态代理类所对应的 Class 对象(即动态生成一个类),该代理类将实现interfaces所指定的所有接口;
- static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h): 创建一个动态代理对象,该代理对象的实现类实现了interfaces对应的所有接口,执行代理对象的每个方法时会被替换成执行InvocationHandler对象(h)的invoke方法。
事实上,采用第一种方式生成动态代理类以后,如果需要创建该代理类对应的对象,依然需要传入一个InvocationHandler对象。
代码示例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PlayerInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object object, Method method, Object[] params) throws Throwable {
System.out.println("I'm dynamicProxy Player");
return null;
}
}
public class DynamicProxyTest {
public static void main(String[] args) {
// 创建被代理类的委托类,之后想要调用被代理类的方法时,都会委托给这个类的invoke(Object object, Method method, Object[] params)方法
PlayerInvocationHandler h = new PlayerInvocationHandler();
//生成代理类
Player proxy = (Player)Proxy.newProxyInstance(Player.class.getClassLoader(), new Class[] {Player.class}, h);
proxy.win();
}
}
执行结果