Java中的代理模式

发表于:2017-2-03 09:35

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:篱开罗    来源:51Testing软件测试网采编

  描述总是比较抽象,还是看实际例子比较好理解
  例子
  InvocationHandler接口的实现类
public class CommonInvocationHandler implements InvocationHandler {
//被代理的对象
private Object proxied;
public CommonInvocationHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在调用被代理对象的方法前做一些事情
System.out.println("before doing something");
//调用被代理对象的方法
Object result = method.invoke(proxied, args);
//在调用被代理对象的方法后做一些事情
System.out.println("after doing something");;
return result;
}
}
  Main
public class Main {
public static void main(String[] args) {
//被代理的对象
Water water = new Water();
//动态获取代理对象
Drink waterProxy =
(Drink) Proxy.newProxyInstance(water.getClass().getClassLoader(),
water.getClass().getInterfaces(),
new CommonInvocationHandler(water));
//通过代理对象调用方法
waterProxy.drink();
}
}
  输出结果
  before doing something
  drink water
  after doing something
  也可以不要具体的被代理对象,但是必须有相应的接口(没有实现接口的类可以使用cglib实现动态代理)才可以动态获取代理对象。像最近比较火的Retrofit就直接通过声明好的接口使用动态代理进行网络请求。
  例子
  简单的模拟一下retrofit
  POST注解
//Post请求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface POST {
String value() default "";
}
  Query注解
//Post请求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface POST {
String value() default "";
}
  Service接口
public interface Service {
//用POST注解声明请求的方式和相对路径
@POST("/login")
//@Query注解声明请求的参数名
void login(@Query("username")String username,
@Query("password")String password);
}
  Main
public class Main {
public static void main(String[] args) {
// 动态获取Service接口的代理
Service service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(),
new Class[] { Service.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 通过注解获取请求的相对路径
String retativePath = ((POST) method.getAnnotations()[0]).value();
System.out.println("relative path: " + retativePath);
// 获取参数的注解
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
// 通过参数的注解获取请求参数
for (int i = 0; i < parameterAnnotations.length; i++) {
if (parameterAnnotations[i].length != 0) {
for (int j = 0; j < parameterAnnotations[i].length; j++) {
Query query = (Query) parameterAnnotations[i][j];
System.out.println(query.value() + ": " + args[i].toString());
}
}
}
return null;
}
});
// 调用代理对象的方法
service.login("hello", "world");
}
}
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号