----------- android培训java培训、java学习型技术博客、期待与您交流! ------------



代理的概念与作用

生活中的代理
武汉人从武汉的代理商手中买联想电脑和直接跑到北京传智播客旁边来找联想总部买电脑,你觉得最终的主体业务目标有什么区别吗?基本上都一样吧,都解决了核心问题,但是,一点区别都没有吗?

程序中的代理
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理等等你准备如何做?
编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时添加系统功能代码。
如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类,还是代理类,这样很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。



AOP面向方面编程(Aspect oriented program,简称AOP)
系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,如下所示
                                  安全      事务         日志
StudentService ---------|----------|------------|------------
CoursetService ---------|----------|------------|------------
MiscService       ---------|----------|------------|------------

用具体的程序代码描述交叉业务:
method1 method2 method3
{               {             {
-------------------------------------------------切面
……… ………… ……….
-------------------------------------------------切面
}              }                 }

交叉业务的编程问题即为面向方面编程AOP,AOP的目标就是要使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码运行效果是一样的,如下所示:
-------------------------------------------------切面
method1 method2 method3
{                {              {
……… ………… ……….
}                }                 }
-------------------------------------------------切面

使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。



动态代理技术
要为系统中的各种接口的类增加代理功能,那将需要太多的代理,全部采用静态代理方式,将是一件非常麻烦的事情!写成百千上万个代理类,是不是太累。
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理
CGLIB库可以动态生成一个类的子类,一个类的子类可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1. 在调用目标方法之前
2. 在调用目标方法之后
3. 在调用目标方法前后
4. 在处理目标方法异常的catch块中



使用Proxy类生成动态代理类
----------获取动态代理类对象的两种方法----------
动态代理类是在运行时指定接口列表的类(所以是动态创建的),构造函数参数是一个InvocationHandler对象,没有无参的构造函数,因为没有任何意义。
1.使用Proxy类静态方法getProxyClass()得到指定接口列表的动态代理类字节码通过构造函数创建动态代理类实例
Class proxyClass = Foo.class.gProxyClass(Foo.class.getClassLoader(),Foo.class);
Constructor constructor = (Constructor)proxyClass.getConstructor(InvocationHandler.class);
Foo f = (Foo)construcor.newInstance(
new InvocationHandler()
{
public Object invoke(Object proxy,Method method,Object... args)
{
//........
}
});
2.直接使用Proxy的静态方法getProxyInstance()构造函数获得动态代理类的实例。因为静态代理类代理某个接口实现类所以它的类型也是接口类型。
Foo f = (Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(),Foo.class,
new InvocationHandler()
{
public Object invoke(Object target,Method method,Object[] arg)
{

}