代理,从字面意思理解,就是要去做一件事,不直接去做,去找中介帮你完成,那中介就算是代理吧。
java语言有静态代理和动态代理,静态代理一个真实角色必须对应一个代理角色,真实角色必须是事先
已经存在的,并作为代理对象的内部属性。看下面实例:
public abstract class Subject
{
public abstract void request();
}
public class RealSubject extends Subject
{
public void request()
{
System.out.println("From real subject.");
}
}
public class ProxySubject extends Subject
{
private RealSubject realSubject;
public void request()
{
this.preRequest(); //在真实角色操作之前所附加的操作
if(null == realSubject)
{
realSubject = new RealSubject();
}
realSubject.request(); //真实角色所完成的事情
this.postRequest(); //在真实角色操作之后所附加的操作
}
private void preRequest()
{
System.out.println("before request");
}
private void postRequest()
{
System.out.println("after request");
}
}
public class Client
{
public static void main(String[] args)
{
Subject subject = new ProxySubject();
subject.request();
}
}
以上程序中,真实角色RealSubject实现Subject接口,代理角色ProxySubject内部含有RealSubject,代理角色内部
实现subject.request(),其实是真实角色realSubject.request(),这就是静态代理模型。
由于静态代理要求真实角色必须事先存在,所以大量使用会导致类的急剧膨胀,就引出了java的动态代理。
java动态代理基于反射实现,是在运行时刻生成的class,假如有一个类A,它实现了interface1和interface2接口,动态代理
就是在运行时刻提供interface1和interface2两个接口给它,它生成一个B对象,该对象宣称实现了interface1,interface2两
个接口,当然你可以把B对象当作interface1和interface2的任何一个来用(父类引用指向子类对象),而实际中你调用B对象完成
的功能都是由A对象来完成的,B对象是A对象实例的代理。
代理实例生成方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
第一个参数为类加载器,就调用真实角色的加载器就可以了(如上面的A),第二个参数为代理实例宣称实现的真实角色所
实现的接口的class类型的数组,第三个参数是一个实现了InvocationHandler接口的类。
InvocationHandler接口里面有个invoke方法,真实角色通过实现invoke方法,完成代理的操作,如下:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
return method.invoke(target, args);
}
反射method对象对应代理角色所调用的方法,target为调用的真实角色的引用。
下面方法返回任意一个对象的代理实例:
public Object getProxy()
{
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method,Object[] args) throws Throwable
{
Object obj = method.invoke(target, args);
return obj;
}
});
return proxy;
}
看下面的应用:
public interface Foo
{
void doAction();
}
public class FooImpl implements Foo
{
public void doAction()
{
System.out.println("in FooImpl doAction!");
}
}
public class CommonInvocationHandler implements InvocationHandler
{
private Object target;
public CommonInvocationHandler(Object target)
{
this.target = target;
}
public CommonInvocationHandler()
{}
public void setTarget(Object target)
{
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
return method.invoke(target, args);
}
}
public class Demo
{
public static void main(String[] args)
{
CommonInvocationHandler handler = new CommonInvocationHandler();
Foo f = null;
handler.setTarget(new FooImpl());
f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class }, handler);
System.out.println(f.getClass().getName());
f.doAction();
}
}
程序输出:$Proxy0
in FooImpl doAction!
FooImpl实现接口Foo,System.out.println("in FooImpl doAction!"),
newProxyInstance方法的handler参数,传入的是真实角色new FooImpl(),
通过handler.setTarget(new FooImpl())把invoke方法中的target设置为new FooImpl(),
Proxy.newProxyInstance产生实例f,f.doAction()方法,实际执行new FooImpl().doAction,
f只是FooImpl实例的一个代理,所以f.getClass().getName()打印$Proxy0。
下面用动态代理实现类似spring的可配置的AOP框架,代码如下:
public class BeanFactory
{
Properties prop = new Properties();
public BeanFactory(InputStream ips)
{
try
{
prop.load(ips);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public Object getBean(String name)
{
String className = prop.getProperty(name);
Object bean = null;
try
{
Class clazz = Class.forName(className);
bean = clazz.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
if (bean instanceof ProxyFactoryBean)
{
Object proxy = null;
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean;
try
{
Advice advice = (Advice) Class.forName(
prop.getProperty(name + ".advice")).newInstance();
Object target = Class.forName(
prop.getProperty(name + ".target")).newInstance();
proxyFactoryBean.setAdvice(advice);
proxyFactoryBean.setTarget(target);
proxy = proxyFactoryBean.getProxy();
}
catch (Exception e)
{
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
//Bean工厂用于从配置文件config.properties中读取信息,如果配置文件key的值为给定真实目标类的全名,
就返回该类的一个实例,如果配置文件key的值为ProxyFactoryBean,就返回目标类的一个代理实例。
public class ProxyFactoryBean
{
private Advice advice;
private Object target;
public Advice getAdvice()
{
return advice;
}
public void setAdvice(Advice advice)
{
this.advice = advice;
}
public Object getTarget()
{
return target;
}
public void setTarget(Object target)
{
this.target = target;
}
public Object getProxy()
{
Object proxy3 = Proxy.newProxyInstance(target.getClass()
.getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable
{
advice.beforeMethod(method);
Object obj = method.invoke(target, args);
advice.afterMethod(method);
return obj;
}
});
return proxy3;
}
}
//代理Bean工厂ProxyFactoryBean,用于生产目标类的一个代理实例,在目标执行系统操作的前后,
还可以加上附带的功能advice.beforeMethod(method)和 advice.afterMethod(method)。我们要做的
就是编写Myadvice类,实现附加功能接口Advice.
public class AopFrameworkTest
{
public static void main(String[] args)
{
InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
Object bean = new BeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
}
}
当配置文件内容为:
xxx=java.util.ArrayList
#xxx=com.aopframework.ProxyFactoryBean
xxx.advice=com.daili.MyAdvice
xxx.target=java.util.ArrayList
程序打印java.util.ArrayList,bean为目标类的一个实例
当配置文件内容为:
#xxx=java.util.ArrayList
xxx=com.aopframework.ProxyFactoryBean
xxx.advice=com.daili.MyAdvice
xxx.target=java.util.ArrayList
程序打印$Proxy0,bean为目标代理类的一个实例。