代理(Proxy)实际上是一种设计模式。代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
//抽象角色:
public interface Subject{
void request();
}
//真实角色:实现了Subject的request()方法。
public class RealSubject implements Subject{
public void request() {
System.out.println("我是真是角色");
}
}
//代理角色:
public class ProxySubject implements Subject{
//以真实角色作为代理角色的属性
private RealSubject realSubject;
public ProxySubject(RealSubject real){
this.realSubject=real;
}
//该方法改变了真是对象的request行为
public void request(){
System.out.println("之前设置新行为" );
realSubject.request(); //此处执行真实对象的request方法
System.out.println("之后设置新行为" );
}
}
//main测试
Subject sub=new ProxySubject();
Sub.request();
从上面的代码可以看出,我们可以通过建立代理角色ProxySubject来改变真实角色中的request方法功能(在原方法前后添加些功能)。这个应用非常的广泛,大家可以想想Struts2框架中拦截器在Action执行前所做的工作。但事实上Struts2框架是如何做到这一点的却是十分的复杂,我们需要往下看。
我们进一步想一下,当我们知道了抽象角色Subject的具体定义(request方法)的时候,我们当然可以很方便的通过包装Subject的真实角色RealSubject来定义一个能够部分改变真实角色行为的代理角色ProxySubject。但是很多情况下,我们事先并不知道需要代理的对象到底是什么类型的。或者说,只有在运行过程中才知道具体的对象。那么我们能否定义
一种具体行为的代理类,能够动态的实例化任何类型的代理对象呢?说白了,我们就是想做到下面这件事:
定义一种具体行为的代理类型:
public class ProxySubject implements interfaceX{
private ClassX obj;
public ProxySubject(ClassX obj){
this.obj=obj;
}
public void methodX(){
....新增行为
obj.methodx();//真实对象行为
....新增行为
}
}
运行时遇到不同类型的对象,都能够使用ProxySubject代理来完成新的行为:
ClassA oa=....
new ProxySubject(oa).methodX;
ClassA ob=....
new ProxySubject(oa).methodX;
做到这一点是很困难的,但并非不可能,Java的代理机制就能够帮助我们完成这件事。
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
(1) InvocationHandler接口,是代理实例的调用处理程序实现的接口。 它只有一个方法:invoke(Object proxy, Method method, Object[] args)。我们需要在实现InvocationHandler接口的具体类中的invoke方法内,编写代理行为的具体逻辑。然后将这个InvocationHandler对象传递给Proxy类中生成一个动态的代理对象。
(2) Proxy 类,提供用于创建动态代理类和实例的静态方法。其最重要的两个静态创建方法:
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
以上面的代码为例,编写一个动态代理类:
//完成代理行为
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
public class DynamicSubject implements InvocationHandler {
private Object sub; //被代理类
public DynamicSubject(Object obj) {
sub = obj;
}
//无论何时调用代理类的方法,都会执行这个invoke方法的。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用被代理对象的方法是:"+method.getName()+" "+method.getDeclaringClass());
System.out.println("之前设置新行为" );
method.invoke(sub,args); //动态调用被代理类的行为方法。
System.out.println("之后设置新行为" );
return null;
}
}
//测试
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.io.*;
static public void main(String[] args) throws Throwable{
Object real=new RealSubject(); //被代理对象
InvocationHandler handler = new DynamicSubject(real); //生成一个具体的代理行为
Object proxyed = Proxy.newProxyInstance(real.getClass().getClassLoader(), real.getClass().getInterfaces(),handler); //动态生成实现Subject接口的代理类
对象
if(proxyed instanceof Subject){
Subject subProx=(Subject)proxyed;
subProx.request();
}
else proxyed.toString();
}
/*
调用被代理对象的方法是:request interface hr.login.Subject
之前设置新行为
我是真是角色
之后设置新行为
*/
相关推荐
java代理机制 JDK动态代理和cglib代理 详解
浅谈java代理机制 .txt 浅谈java代理机制 .txt
NULL 博文链接:https://xueyue.iteye.com/blog/1202897
只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,
java反射机制和动态代理的原理,熟悉反射机制和动态代理
Java动态代理机制详解[整理].pdf
java反射机制与动态代理 java反射机制 java反射机制java反射机制java反射机制java反射机制
JAVA的反射机制与动态代理
主要讲述Java反射机制与设计模式之一:代理模式的原理与应用;同时详细讲述了Java对代理模式的支持以及Java中动态代理的原理,应用与实践。
JAVA 反射机制与动态代理ppt,郎溪出品
该源码包含Java语言的动态代理和静态代理的详细demo,适合初学者系统了解Java代理机制
Java动态代理机制详解_动力节点Java学院整理,动力节点口口相传的Java黄埔军校
一个有关JAVA动态代理机制的例子,用eclipse开发的,如果有对Java有兴趣的朋友,不妨先拿去看一看。
Java反射机制与动态代理 浪曦 Java Reflection API 简介 及动态代理
java动态代理的机制分析,以及相应的拓展。有详细的代码和实例加以分析。
详细介绍了Java的动态代理机制 是学习Java反射与动态代理的不错资料
JAVA反射机制与动态代理.part04
package com.gc.aop下为:aop方式... ... ... ... ... package com.gc.javaproxy下为:java代理机制实现 package com.gc.proxy下为:自定义代理模式(面向接口编程) package com.gc.normal下为:通用日志处理方式
JAVA反射机制与动态代理 介绍java的反射机制和动态代理