当前位置:
文档之家› JAVA动态代理及在HSF中的应用
JAVA动态代理及在HSF中的应用
14
方法二:
15
JAVA动态代理在HSF中的应用
• HSF在淘宝应用中使用比较广泛,虽然配置简单,但在使用时 会有些限制或者其他一些异常, 比如通过HSF调用服务参数传递问 题等…, 简单配置的背后掩盖了更多的实现细节, 导致开发人员碰到 异常时难以下手。下面就和大家讨论下HSF中消费端的加载过程及 调用服务的实现。
4
JAVA动态代理示例
–一个简单例子 –了解动态代理类结构 –扩展代理类功能
5
一个简单例子
/** * 日志接口 * @author gaoxuan 2009-11-29 * */ public interface Log { /** * 记录日志的方法 * @param log */ public void writeLog(String log); }
7
现在需要增加日志输出时间
/** * 添加时间记录 * @author gaoxuan 2009-11-29 */ public class LogProxy4Time implements InvocationHandler { private Log realObject; // 需要被代理的对象 public LogProxy4Time(Log realObject) { this.realObject = realObject; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; if(this.realObject == null) { return obj; } if("writeLog".equalsIgnoreCase(method.getName())) { System.out.println(new Date()); obj = method.invoke(realObject, args); System.out.println(new Date()); } return obj; } }
JAVA动态代理及在HSF中的应用
部门:咨询门户 日期:2009-12-2 高轩
1
•Java动态代理介绍 •Java动态代理示例
–一个简单例子 –了解动态代理类结构 –扩展代理类功能
•Java动态代理在HSF中的应用 •题外话:HSF参数传递返回结果的限制
2
JAVA动态代理介绍
• 所谓Dynamic Proxy是这样一种class:它是在运行时生成 的class,在生成它时你必须提供一组interface给它,然后该 class就宣称它实现了这些interface。然后你就可以把该class的 实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生 成它的实例时你必须提供一个InvocationHandler的实例,由它 接管实际的工作
6
/** * 日志接口的实现类 * @author gaoxuan 2009-11-29 * */ public class LogImpl implements Log{ /** * 记录日志的方法 */ public void writeLog(String log) { System.out.println(log); } }
XML: <bean id="helloWorldService" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean" init-method="init"> <property name="interfaceName" value="com.taobao.hsf.example.service.HelloWorld" /> <property name="version" value="1.0.0" /> <property name="target" value="localhost:12200?_TIMEOUT=1000" /> </bean> JAVA: HelloWorld service = (HelloWorld) context.getBean("helloWorldService"); service.getRegard(); Spring配置的BEAN的类型是com.taobao.hsf.app.spring.util.HSFSpringConsumerBean, 为什么能转换成HelloWorld类型?
a. HSFSpringConsumerBean 实现了FactoryBean接口, FactoryBean接口用 于在Spring中创建其他类 型的Bean b. 实际上生成的是一个实现了指定接口的代理类
18
HSF消费者BEAN生成的动态代理类型UML图
初始化代码片段: Init(){ … Class<?> interfaceClass=Class.forName(interfaceName); handler=new HSFSpringConsumerBeanHandler(target,interfaceName,versio n); proxyObj=Proxy.newProxyInstance(HSFSpringConsumerBean.clas s.getClassLoader(),new Class[]{interfaceClass,HSFSpringHandler.class},handler); …}
12
扩展代理类功能
–目前输出日志时能够记录时间,假如系统运 行期间需要改变代理功能, 输出日志时需要 记录时间和其他信息,或者需要格式化的时间 该怎么办? –下面用UML图描述了两种实现方法, 具体 代码不做展示,有兴趣可以看示例程序. 其中 第二种方法是目前HSF消费者实现中所采用 的。
13
方法一:
8
测试运行
public static void main(String[] args) { // 生成Log实现对象 LogImpl log = new LogImpl(); // 生成一个代理类 Object proxy = Proxy.newProxyInstance(log.getClass() .getClassLoader(), log.getClass().getInterfaces(), new LogProxy4Time(log)); //或者 //Class cls = Proxy.getProxyClass(log.getClass().getClassLoader(), new Class[]{Log.class}); //Constructor con = cls.getConstructor(new Class[]{InvocationHandler.class}); //Object proxy = con.newInstance(new Object[]{new LogProxy4Time(log)}); // proxy已经实现了Log接口,故转型为Log Log proxyLog = (Log) proxy; // 调用Log接口方法 proxyLog.writeLog("调用Log接口方法"); } 输出结果: Wed Dec 02 09:52:27 CST 2009 输出日志 Wed Dec 02 09:52:27 CST 2009
11
public final void writeLog(String paramString) throws { try { this.h.invoke(this, m3, new Object[] { paramString }); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } static { try { m3 = Class.forName(“com.test.Log”).getMethod(“writeLog”, new Class[] { Class.forName(“ng.String”) }); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } } 现在代理类的结构应该已经很清楚了
(2)Proxy:该类即为动态代理类, 其中主要包含以下内容:Protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值, Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获 得一个代理类,其中loader是类装载器,interfaces是真实类所拥有 的全部接口的数组。Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个 实例,返回后的代理类可以当作被代理类使用