代理: 我提供一些服务,但我不直面客户,由代理商来跟客户交涉。
案例: 使用代理,来模拟MVC中 C
代理应用场景:
Proxy模式常见情况:
1) 远程代理(Remote Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又叫做大使(Ambassador)
2) 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
3) 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
4) 智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。
5) Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。
静态代理模式UML图:
类介绍:
UParamAttr 参数绑定注解(方法参数注解)
URequestMapper :请求路径注解 (方法注解)
UAction :action类注解
UserAction : 用户action类(服务提供者)
ActionProxy : action代理类(代理商)
ActionProxyFactory: 工厂类,用来获取代理
DB: 假数据库
URequest :请求数据简单封装,模拟HTTP request
User : 实体bean
TestMain: 测试类
代码截图如下:
action类标记注解
package com.bo.proxy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
* @Target 说明了Annotation所修饰的对象范围:
* Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、
* 类型成员(方法、构造方法、成员变量、枚举值)、
* 方法参数和本地变量(如循环变量、catch参数)。
* 在Annotation类型的声明中使用了target可更加明晰其修饰的目标
*
* @Retention定义了该Annotation被保留的时间长短:
* 某些Annotation仅出现在源代码中,而被编译器丢弃;
* 而另一些却被编译在class文件中;
* 编译在class文件中的Annotation可能会被虚拟机忽略,
* 而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。
* 使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
*/
@Retention(value=RetentionPolicy.RUNTIME)
@Target(value=ElementType.TYPE)
/**
* action标记
* @author 波
*
*/
public @interface UAction {
public String value() default "";
}
参数绑定注解:
package com.bo.proxy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 参数绑定注解
* @author 波
*
*/
@Retention(value=RetentionPolicy.RUNTIME)
@Target(value=ElementType.PARAMETER)
public @interface UParamAttr {
public String value() default "";
}
请求路径注解:
package com.bo.proxy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 请求路径注解
* @author 波
*
*/
@Retention(value=RetentionPolicy.RUNTIME)
@Target(value=ElementType.METHOD)
public @interface URequestMapper {
String value() default "";
}
用户控制类action:
package com.bo.proxy;
import java.util.List;
@UAction
public class UserAction {
@URequestMapper("/list")
public List<User> list(){
return DB.queryUserList();
}
@URequestMapper("/add")
public Object addUser(@UParamAttr("userinfo") User u){
return DB.addUser(u);
}
@URequestMapper("/remove")
public Object removeUser(@UParamAttr("userinfo") User u){
return DB.removeUser(u);
}
}
action代理类:
package com.bo.proxy;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
public class ActionProxy implements InvocationHandler {
private Object object;
public ActionProxy(Object object) {
// TODO Auto-generated constructor stub
this.object = object;
}
public void before(){}
public void after(){}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
this.before();
Object object = method.invoke(this.object, args);
this.after();
return object;
}
public Object execute(URequest request) throws Throwable{
String path = request.getPath();
Map<String,Object> requestParam = request.getRequestParam();
Object result =null;
Method[] methods = this.object.getClass().getMethods();
for(int index=0;index<methods.length;index++){
Method method = methods[index];
URequestMapper uRequestMapper = method.getAnnotation(URequestMapper.class);
if(uRequestMapper!=null){
String mapperPath = uRequestMapper.value();
if(mapperPath.equals(path)){
Class<?>[] cls = method.getParameterTypes();
Annotation[][] paraAnnotations = method.getParameterAnnotations();
Object[] args = new Object[cls.length];
for(int paraAnnIndex=0;paraAnnIndex<paraAnnotations.length;paraAnnIndex++){
Annotation[] annotaion = paraAnnotations[paraAnnIndex];
for(int cParaAnnIndex=0;cParaAnnIndex<annotaion.length;cParaAnnIndex++){
Annotation tAnnotaion = annotaion[cParaAnnIndex];
if(tAnnotaion instanceof UParamAttr){
UParamAttr uParamAttr=(UParamAttr)tAnnotaion;
String paramKey = uParamAttr.value();
//Object obj = cls[paraAnnIndex].newInstance();
args[paraAnnIndex] =requestParam.get(paramKey);
}
}
}
result = method.invoke(this.object, args);//this.invoke(this.object, method, args) ;//this.invoke(this.object, args);
/*for(int ptIndex=0;ptIndex<cls.length;ptIndex++){
cls[ptIndex];
}*/
break;
}
}
}
return result;
}
}
代理工厂类:
package com.bo.proxy;
public class ActionProxyFactory {
public static Object newInstaces(Class cls) throws IllegalArgumentException, InstantiationException, IllegalAccessException{
// return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), cls.getInterfaces(),);
return new ActionProxy(cls.newInstance());
}
}
假数据库:
package com.bo.proxy;
import java.util.ArrayList;
import java.util.List;
public class DB {
private static List<User> userList = new ArrayList<>();
static{
userList = (userList!=null? userList:new ArrayList<User>());
for(int i=0;i<5;i++){
User u = new User();
u.setUid("uid00"+i);
u.setUname("uname00"+i);
userList.add(u);
}
}
public static List<User> queryUserList(){
return DB.userList;
}
public static boolean removeUser(User u){
return DB.userList.remove(u);
}
public static boolean addUser(User u){
return DB.userList.add(u);
}
}
请求数据封装-模拟http request:
package com.bo.proxy;
import java.util.Map;
public class URequest {
private String path ;
private Map<String,Object> requestParam ;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Map<String, Object> getRequestParam() {
return requestParam;
}
public void setRequestParam(Map<String, Object> requestParam) {
this.requestParam = requestParam;
}
}
测试类:
package com.bo.proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestMain {
public static void main(String[] args) throws Throwable {
// TODO Auto-generated method stub
ActionProxy proxy = (ActionProxy) ActionProxyFactory.newInstaces(UserAction.class);
System.out.println("添加用户:");
URequest addRequest = new URequest();
addRequest.setPath("/add");
Map<String,Object> userInfo = new HashMap<>();
User u = new User();
u.setUid("uid-0001");
u.setUname("uname-0001");
userInfo.put("userinfo", u);
addRequest.setRequestParam(userInfo);
boolean b = (boolean) proxy.execute(addRequest);
System.out.println(b?"添加成功":"添加失败");
System.out.println("所有用户列表:");
URequest request = new URequest();
request.setPath("/list");
List<User> list = (List<User>) proxy.execute(request);
for(int index = 0;index<list.size();index++){
System.out.println(list.get(index).toString());
}
}
}
输出:
添加用户:
添加成功
所有用户列表:
User [uid=uid000, uname=uname000]
User [uid=uid001, uname=uname001]
User [uid=uid002, uname=uname002]
User [uid=uid003, uname=uname003]
User [uid=uid004, uname=uname004]
User [uid=uid-0001, uname=uname-0001]