代理类的作用,顾名思义,代理类,是类的代理,将类给代理,不直接调用类的方法,而通过代理来调用。
构造方法:
private Proxy() {
}
protected Proxy(InvocationHandler h) {
this.h = h;
}
由这个可以知道这个类是不能直接new 的,查看api,提供调用见下
Proxy
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
创建某一接口 Foo
的代理:
InvocationHandler handler = new MyInvocationHandler(...);
Class proxyClass = Proxy.getProxyClass(
Foo.class.getClassLoader(), new Class[] { Foo.class });
Foo f = (Foo) proxyClass.
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
或使用以下更简单的方法:
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler)
代理类可以用作aop做,调用方法前的一些操作,相当于是一个before操作,当通过代理类获取到对象,用该对象调用代理方法将会有一个inoke操作 。实现invoke操作需要实现InvocationHandler接口,这也是实现代理方法的很重要的一步,代理的方法需要通过该接口的实现类进行invoke操作
下面创建一个使用代理类的简单实例。实例实现的目标是。在老师工作的时候是上课,在工作之前需要准备课前操作。
详细步骤如下:
1.创建work接口IWork,该接口定义一个工作方法,
2.创建IWork接口的实现类TeacherWoke,
3.将work方法交给work代理类代理,创建WorkProxy代理类
4.实现InvocationHandler接口
第一步创建接口:
public interface IWork {
public void work();
}
第二部实现接口
public class TeacherWoke implements IWork{
@Override
public void work() {
// TODO Auto-generated method stub
System.out.println("老师上上课");
}
}
第三部创建代理类:
public class WorkProxy {
public IWork work;
public WorkProxy(IWork work) {
// TODO Auto-generated constructor stub
this.work = work;
}
public IWork createWorkProxy(){
InvocationHandler handler = new WorkHandler(work);
Class>[] iterfaces = new Class[]{IWork.class};
return (IWork)Proxy.newProxyInstance(IWork.class.getClassLoader(), iterfaces, handler);
}
}
第四部实现InvocationHandler:接口
public class WorkHandler implements InvocationHandler {
private IWork work;
public WorkHandler(IWork work) {
// TODO Auto-generated constructor stub
this.work=work;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
//老师工作之前需要先准备课件,讲义,等课前准备
preWork();
Object ret = method.invoke(work,args);
return ret;
}
private void preWork() {
// TODO Auto-generated method stub
System.out.println("老师工作之前需要先准备课件,讲义,等课前准备");
}
}
测试代码如下:
public class TestWorkClient {
@Test
public void testWorkProxy() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, InterruptedException{
IWork teachwork = new TeacherWoke();
WorkProxy workproxy = new WorkProxy(teachwork);
IWork work = workproxy.createWorkProxy();
work.work();
}
}
特别说明
对代码进行一些说明类WorkHandler中的invoke方法的api如下
参数:
proxy
- 在其上调用方法的代理实例
method
- 对应于在代理实例上调用的接口方法的
Method
实例。
Method
对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args
- 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为
null
。基本类型的参数被包装在适当基本包装器类(如
java.lang.Integer
或
java.lang.Boolean
)的实例中。
返回:从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为
null
并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出
NullPointerException
。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出
ClassCastException
。