定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
用自己的话说:把真正运行的类封装到代理类里面,当实际调用时通过代理类去调用,代理类与真正运行的类实现同一套接口,代理类可以在真正操纵前对动作进行一些处理,适用为
远程代理:远程链接时,通过代理类隐藏网络获取等相关动作。
虚拟代理:使用代理代表开销大的对象或需要安全控制的对象
缓存代理:使用代理判断当前获取的内容是否已被缓存,是则调用缓存返回,否则调用真实的类进行获取。
保护代理:隐藏主体的某些动作,或屏蔽某些数据
java有提供相关api
简单的代理代码:
定义一个主体接口:
public interface Subject {
void request();
}
定义一个真正的实体类:
public class RealSubject implements Subject {
/* (非 Javadoc)
* @see com.jjt.proxy.Subject#request()
*/
@Override
public void request() {
System.out.println("真正做事的对象执行请求");
}
}
定义一个代理:
public class Proxy implements Subject {
Subject realSubject = new RealSubject();
/* (非 Javadoc)
* @see com.jjt.proxy.Subject#request()
*/
@Override
public void request() {
System.out.println("代理类调用实体类");
System.out.println("省略网络请求");
realSubject.request();
}
}
测试:
public static void main(String[] args){
Subject proxy = new Proxy();//新建一个代理去请求
proxy.request();
}
结果:
代理类调用实体类
省略网络请求
真正做事的对象执行请求
———————————————————————————————
动态代理,使用java api
代码:
定义一个人的接口:
/**
* 代理与真正执行服务类继承的同个接口
* @author jiangjintai
*
*/
public interface PersonBean {
String getName();
String getGender();
String getInterests();
int getHotOrNotRating();
void setName(String name);
void setGender(String gender);
void setInterests(String interests);
void setHotOrNotRating(int rating);
}
定义一个人的实现:
public class PersonBeanImpl implements PersonBean {
String name;
String gender;
String interests;
int rating;
int ratingCount = 0 ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getInterests() {
return interests;
}
public void setInterests(String interests) {
this.interests = interests;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public int getRatingCount() {
return ratingCount;
}
public void setRatingCount(int ratingCount) {
this.ratingCount = ratingCount;
}
/* (非 Javadoc)
* @see com.jjt.proxy.javaapi.PersonBean#getHotOrNotRating()
*/
@Override
public int getHotOrNotRating() {
//
if(ratingCount==0) return 0;
return (rating/ratingCount);//返回平均分
}
/* (非 Javadoc)
* @see com.jjt.proxy.javaapi.PersonBean#setHotOrNotRating(int)
*/
@Override
public void setHotOrNotRating(int rating) {//设置分数
this.rating+=rating;
ratingCount++;
}
}
定义一个handle 用于控制动态代理类对实体类的操作
第一个handle 是不允许用户本人对自己设置分数
/**
* InvocationHandler 是代理实例的调用处理程序 实现的接口
* 每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法
* @author jiangjintai
*
*/
public class OwnerInvocationHandler implements InvocationHandler {
PersonBean personBean;
/**
*
*/
public OwnerInvocationHandler(PersonBean personBean) {
this.personBean=personBean;
}
/* (非 Javadoc)
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().startsWith("get")){
return method.invoke(personBean, args);
}else if(method.getName().equals("setHotOrNotRating")){//在这里屏蔽设置分数方法
throw new IllegalAccessError();
}else if(method.getName().startsWith("set")){
return method.invoke(personBean, args);
}
return null;//别的方法不做处理
}
}
第二个handle 是不允许别人对某个用户设置兴趣
public class NonOwnerlnvocationHandler implements InvocationHandler {
PersonBean personBean;
/**
*
*/
public NonOwnerlnvocationHandler(PersonBean personBean) {
this.personBean=personBean;
}
/* (非 Javadoc)
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().startsWith("get")){
return method.invoke(personBean, args);
}else if(method.getName().startsWith("setInterests")){//屏蔽方法
throw new IllegalAccessError();
}else if(method.getName().startsWith("set")){
return method.invoke(personBean, args);
}
return null;
}
}
测试方法:
public static void main(String[] args){
PersonBean personBean = new PersonBeanImpl();
personBean.setGender("男");
personBean.setHotOrNotRating(100);
personBean.setInterests("下棋");
personBean.setName("泰");
PersonBean ownerProxy = (PersonBean) Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(),new OwnerInvocationHandler(personBean));
ownerProxy.setGender("女");
PersonBean nonOwnerProxy = (PersonBean)Proxy.newProxyInstance(personBean.getClass().getClassLoader(),personBean.getClass().getInterfaces(), new NonOwnerlnvocationHandler(personBean));
System.out.println(nonOwnerProxy.getGender());
}
测试:
public static void main(String[] args){
PersonBean personBean = new PersonBeanImpl();
personBean.setGender("男");
personBean.setHotOrNotRating(100);
personBean.setInterests("下棋");
personBean.setName("泰");
PersonBean ownerProxy = (PersonBean) Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(),new OwnerInvocationHandler(personBean));
ownerProxy.setGender("女");
// ownerProxy.setHotOrNotRating(10); 调用该方法抛出java.lang.IllegalAccessError异常
PersonBean nonOwnerProxy = (PersonBean)Proxy.newProxyInstance(personBean.getClass().getClassLoader(),personBean.getClass().getInterfaces(), new NonOwnerlnvocationHandler(personBean));
System.out.println(nonOwnerProxy.getGender());
// nonOwnerProxy.setInterests("吹牛");调用该方法抛出java.lang.IllegalAccessError异常
}