Java代理模式

1.java反射机制
理解代理模式的前提是先理解java中的反射机制,先看一个例子:
JDBC加载驱动时,Class.forName(“com.mysql.jdbc.Driver”); 此时通过反射加载连接mysql数据库的jar包,该句等价于import com.mysql.jdbc.Driver; 可是为什么不直接导入呢?这就是反射设计的合理之处了。
(1)用反射可以在运行时动态导入,直接导入是在编译时就确定com.mysql.jdbc.Driver包必须存在,否则编译不过,这样看来,加上反射,可执行的范围增大了。
(2)提高复用率,加上反射,Class.forName(“从配置文件读取具体的包内容”),这样,当你更换数据库时,只需更改配置文件,而不用像导入的方式那样挨个更换你的import。 java反射就是在运行时动态获取类的信息,方法,构造方法等信息。可以加载一个在运行时才确定其名称信息的类,并确定该类的基本信息。
由反射引出的设计模式-代理模式
Java编程的目标是实现现实不能完成的,优化现实能够完成的,是一种虚拟技术。生活中的方方面面都可以虚拟到代码中。代理模式所讲的就是现实生活中的这么一个概念:中介。代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式有几种,虚拟代理,计数代理,远程代理,动态代理。主要分为两类,静态代理和动态代理。
代理模式包含如下角色
ISubject:抽象主题角色,是一个接口。该接口是对象和它的代理共用的接口。
RealSubject:真实主题角色,是实现抽象主题接口的类。
Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象提供与真实对象相同的接口,以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

实现动态代理的关键技术是反射。
静态代理
静态代理比较简单,是由程序员编写的代理类,并在程序运行前就编译好的,而不是由程序动态产生代理类,这就是所谓的静态。
考虑这样的场景,管理员在网站上执行操作,在生成操作结果的同时需要记录操作日志,这是很常见的。此时就可以使用代理模式,代理模式可以通过聚合和继承两种方式实现:
聚合实现方式中代理类聚合了被代理类,且代理类及被代理类都实现了同一个接口,可实现灵活多变。继承式的实现方式则不够灵活。
比如,在管理员操作的同时需要进行权限的处理,操作内容的日志记录,操作后数据的变化三个功能。三个功能的排列组合有6种,也就是说使用继承要编写6个继承了Admin的代理类,而使用聚合,仅需要针对权限的处理、日志记录和数据变化三个功能编写代理类,在业务逻辑中根据具体需求改变代码顺序即可。

public interface People {  
    public void execute();
}
public class My implements People { 
@Override 
    public void execute() { 
        System.out.println("拿外卖");
    } 
}
public class WaiMaiXiaoGe implements People {     	
    public My my;    
    public WaiMaiXiaoGe(My my){        
    	this.my=my;    
    }   
    @Override    
    public void execute() {        
    	System.out.println("打包外卖");       
    	my.execute();        
    	System.out.println("送外卖结束");     
    }
}

动态代理
一般来说,对代理模式而言,一个主题类与一个代理类一一对应,这也是静态代理模式的特点。
但是,也存在这样的情况,有n各主题类,但是代理类中的“前处理、后处理”都是一样的,仅调用主题不同。也就是说,多个主题类对应一个代理类,共享“前处理,后处理”功能,动态调用所需主题,大大减小了程序规模,这就是动态代理模式的特点。

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理。在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样对每一个方法或方法组合进行处理。虽然Proxy很强大,但是仅支持 interface 代理。Java 的单继承机制就注定了这些动态代理类们无法实现对 class 的动态代理。好在有cglib为Proxy提供了弥补。class与interface的区别本来就模糊,在java8中更是增加了一些新特性,使得interface越来越接近class,当有一日,java突破了单继承的限制,动态代理将会更加强大。
JDK动态代理具体过程:
1.定义一个事件管理器类实现invocationHandle接口,并重写invoke(代理类,被代理的方法,方法的参数列表)方法。
2.实现被代理类及其实现的接口。
3.调用Proxy.newProxyInstance(类加载器,类实现的接口,事务处理器对象);生成一个代理实例。
4.通过该代理实例调用方法。

public class My implements People { 
@Override  
    public void execute() { 
    	System.out.println("拿外卖"); 
    } 
} 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; 

public class Handler implements InvocationHandler {    
    private Object o = null;     
    public Handler(Object o) {        
    	this.o = o;     
    }     
    @Override    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{      
	System.out.println("外卖小哥取外卖");        
	method.invoke(o, args);        
	System.out.println("送外卖完成");        
	return null;    
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; 

public class Handler implements InvocationHandler {     
    private Object o = null;     
    public Handler(Object o) {        
    	this.o = o;     
    }     
    @Override    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        
        System.out.println("外卖小哥取外卖");        
        method.invoke(o, args);        
        System.out.println("送外卖完成");       
        return null;    
    }
 }

优点
1)良好的扩展性。修改被代理角色并不影响调用者使用代理,对于调用者,被代理角色是透明的。
2)隔离,降低耦合度。代理角色协调调用者和被代理角色,被代理角色只需实现本身关心的业务,非自己本职的业务通过代理处理和隔离。
缺点 增加了代理类,实现需要经过代理,因此请求速度会变慢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值