代理
例如
structs2里面的拦截器,网络代理,翻墙等等。
这里就不多叙述其他高级的代理模式了,学的很肤浅,没有实际应用到项目中去,这个暑假,只是拓宽一下眼界而已,让自己有个印象。
普通代理(静态代理)
public abstract class IGamePlayer {
public abstract void fightBoss();
public abstract void login(String uname,String pwd);
public abstract void upgrade();
}
public class GamePlayer extends IGamePlayer {
private String name="";
public GamePlayer(String name){
this.name=name;
}
@Override
public void fightBoss() {
System.out.println(this.name+"在打怪");
}
@Override
public void upgrade() {
System.out.println(this.name+"升级了");
}
@Override
public void login(String uname, String pwd) {
System.out.println(uname+"登录,时间"+new Date());
}
}
public class GamePlayerProxy extends IGamePlayer {
private IGamePlayer gamePlayer=null;
public GamePlayerProxy(GamePlayer gamePlayer){
this.gamePlayer=gamePlayer;
}
@Override
public void fightBoss() {
this.gamePlayer.fightBoss();
}
@Override
public void login(String uname, String pwd) {
this.before();
this.gamePlayer.login(uname, pwd);
}
@Override
public void upgrade() {
this.gamePlayer.upgrade();
this.after();
}
public void before(){
System.out.println("开始代理");
}
public void after(){
System.out.println("结束代理");
}
}
public class Client {
public static void main(String[] args) {
GamePlayer player=new GamePlayer("大宝");
GamePlayerProxy proxy=new GamePlayerProxy(player);
proxy.login("大宝","a");
proxy.fightBoss();
proxy.upgrade();
}
}
上面的例子非常简单,权当入门看看,有点感觉。
下面来一个有意思的代理,叫做强制代理,意思就是只能通过真实类来找到代理,而上面的静态代理是通过代理来找到真实类,从而达到访问目的。
强制代理
//强制代理 必须通过真实类找到代理
//普通代理 通过代理找到真实类
public abstract class IGamePlayer {
public abstract void fightBoss();
public abstract void login(String uname,String pwd);
public abstract void upgrade();
public abstract IGamePlayer getProxy();
}
public class GamePlayerProxy extends IGamePlayer {
private IGamePlayer gamePlayer=null;
public GamePlayerProxy(IGamePlayer gamePlayer){
this.gamePlayer=gamePlayer;
}
@Override
public void fightBoss() {
this.gamePlayer.fightBoss();
}
@Override
public void login(String uname, String pwd) {
this.before();
this.gamePlayer.login(uname, pwd);
}
@Override
public void upgrade() {
this.gamePlayer.upgrade();
this.after();
}
public void before(){
System.out.println("开始代理");
}
public void after(){
System.out.println("结束代理");
}
//暂时没有,就是自己
@Override
public IGamePlayer getProxy() {
return this;
}
}
public class GamePlayer extends IGamePlayer {
private String name="";
private IGamePlayer proxy=null;
@Override
public IGamePlayer getProxy() {
this.proxy=new GamePlayerProxy(this);
return this.proxy;
}
public GamePlayer(String name){
this.name=name;
}
@Override
public void fightBoss() {
if(this.isProxy()){
System.out.println(this.name+"在打怪");
}else{
System.out.println("请使用指定的代理访问");
}
}
@Override
public void upgrade() {
if(this.isProxy()){
System.out.println(this.name+"升级了");
}else{
System.out.println("请使用指定的代理访问");
}
}
@Override
public void login(String uname, String pwd) {
if(this.isProxy()){
System.out.println(uname+"登录,时间"+new Date());
}else{
System.out.println("请使用指定的代理访问");
}
}
private boolean isProxy(){
if(this.proxy==null){
return false;
}else{
return true;
}
}
}
public class Client {
public static void main(String[] args) {
/* GamePlayer player=new GamePlayer("大宝");
player.login("大宝","a");
player.fightBoss();
player.upgrade();*/
/*IGamePlayer player=new GamePlayer("大宝");
IGamePlayer proxy=new GamePlayerProxy(player);
proxy.login("大宝","a");
proxy.fightBoss();
proxy.upgrade();*/
IGamePlayer player=new GamePlayer("大宝");
IGamePlayer proxy=player.getProxy();
proxy.login("大宝", "a");
proxy.fightBoss();
proxy.upgrade();
}
}
分析测试
第一个直接使用真实类访问,自然无法访问。因为在其业务方法中指定需要代理。
第二种通过真实类得到一个代理对象,这样的话是通过代理来访问真实类,和静态代理一样。
第三种通过真实类得到一个代理对象,再实现访问。
动态代理
大致分为四步,其中详细的就不多说了。可以参照博客。 http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))
public class GamePlayIH implements InvocationHandler {
// Class cls=null; //被代理者
Object obj=null; //被代理的实例
public GamePlayIH(Object _obj){
this.obj=_obj;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=method.invoke(this.obj, args);
if(method.getName().equalsIgnoreCase("login")){
System.out.println("有人用我的账号登陆");
}
return result;
}
}
public static void main(String[] args) {
GamePlayer player = new GamePlayer("大宝");
InvocationHandler handler = new GamePlayIH(player);
ClassLoader cl = player.getClass().getClassLoader();
IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl,
new Class[] { IGamePlayer.class }, handler);
proxy.login("大宝", "a");
proxy.fightBoss();
proxy.upgrade();
}
这里有个地方需要说明,Proxy仅仅支持interface代理,也就是说,IGamePlayer只能是接口,而不能是抽象类,细心的可能发现上面写的都是使用了抽象类。再细心的可以发现我在实例化GamePlayer("大宝")时没有使用多态,失误失误。 这样看来,动态代理完全是面向接口编程,抽象层面的底层编程。
public interface IGamePlayer {
public void fightBoss();
public void login(String uname, String pwd);
public void upgrade();
}
public class GamePlayer implements IGamePlayer {
private String name="";
public GamePlayer(String name){
this.name=name;
}
public void fightBoss() {
System.out.println(this.name+"在打怪");
}
public void login(String uname, String pwd) {
System.out.println(uname+"登录,时间"+new Date());
}
public void upgrade() {
System.out.println(this.name+"升级");
}
}
将上述的多个流程整合成一起
public class DynamicProxy<T> {
public static <T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){
//寻找JoinPoint连接点,AOP框架使用元数据定义
if(true){
//XXX执行
System.out.println("执行到这里来了");
}
return (T) Proxy.newProxyInstance(loader, interfaces, h);
}
}
再进一步的整理
public class SubjectDynamicProxy extends DynamicProxy {
public static <T> T newProxyInstance(IGamePlayer gamePlayer){
ClassLoader loader=gamePlayer.getClass().getClassLoader();
Class<?>[] interfaces=gamePlayer.getClass().getInterfaces();
InvocationHandler handler=new GamePlayIH(gamePlayer);
return newProxyInstance(loader, interfaces, handler);
}
}
调用
public static void main(String[] args) {
GamePlayer player = new GamePlayer("大宝");
InvocationHandler handler = new GamePlayIH(player);
IGamePlayer proxy =DynamicProxy.newProxyInstance(player.getClass().getClassLoader(),
player.getClass().getInterfaces(), handler);
proxy.login("大宝", "a");
proxy.fightBoss();
proxy.upgrade();
}
public static void main(String[] args) {
GamePlayer player = new GamePlayer("大宝");
IGamePlayer proxy =SubjectDynamicProxy.newProxyInstance(player);
proxy.login("大宝", "a");
proxy.fightBoss();
proxy.upgrade();
}
我是菜鸟,我在路上。