/**
* 代理模式:
* 为另一个对象提供一个占位符或者替身,以控制对这个对象的访问
*
* 按照控制方式的不同:
* 远程代理-->控制访问远程对象(不在同一个JVM的对象)
* 虚拟代理-->控制访问大开销资源的对象(网络或者IO对象)
* 保护代理-->基于权限控制对资源的访问(不同的权限,对资源的访问层次不同)
* 缓存代理-->为开销大的运算结果提供暂时的存储
* 智能引用代理-->当主题被引用时,进行额外的操作
* 防火墙代理-->控制网络资源的访问
* 同步代理-->在多线程的情况下为主题提供安全的访问
* 复杂隐藏代理-->用来隐藏一个类的复杂度并进行访问控制
* 写入时复制代理-->用来控制对象的复制
*
* 模式对比:
* 装饰者模式-->包装一个对象,对其提供额外的功能
* 适配器模式-->包装一个对象,并提供不同的接口
* 外观模式-->包装许多对象以提供访问的简单接口
* 代理模式 -->包装一个对象,以控制对它的访问
*
*
* 示例:
* 远程代理使用RMI作为示例 ,远程访问的还有EJB和WEBSERVICES
* 虚拟代理使用网络资源的加载作为示例,利用JFRAME作为示例
* 保护代理使用资源的访问作为示例,像SPRING的AOP就用了保护代理
*
*
*
* @author Administrator
*
*/
1、先看RMI示例的远程代理
RMI参考之前的文章 http://blog.csdn.net/undergrowth/article/details/24913031
远程服务接口
package com.undergrowth.proxy;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 代理模式:
* 为另一个对象提供一个占位符或者替身,以控制对这个对象的访问
*
* 按照控制方式的不同:
* 远程代理-->控制访问远程对象(不在同一个JVM的对象)
* 虚拟代理-->控制访问大开销资源的对象(网络或者IO对象)
* 保护代理-->基于权限控制对资源的访问(不同的权限,对资源的访问层次不同)
* 缓存代理-->为开销大的运算结果提供暂时的存储
* 智能引用代理-->当主题被引用时,进行额外的操作
* 防火墙代理-->控制网络资源的访问
* 同步代理-->在多线程的情况下为主题提供安全的访问
* 复杂隐藏代理-->用来隐藏一个类的复杂度并进行访问控制
* 写入时复制代理-->用来控制对象的复制
*
* 模式对比:
* 装饰者模式-->包装一个对象,对其提供额外的功能
* 适配器模式-->包装一个对象,并提供不同的接口
* 外观模式-->包装许多对象以提供访问的简单接口
* 代理模式 -->包装一个对象,以控制对它的访问
*
*
* 示例:
* 远程代理使用RMI作为示例 ,远程访问的还有EJB和WEBSERVICES
* 虚拟代理使用网络资源的加载作为示例,利用JFRAME作为示例
* 保护代理使用资源的访问作为示例,像SPRING的AOP就用了保护代理
*
*
*
* @author Administrator
*
*/
public interface GumballMachineRemote extends Remote{
/**
* 每个方法都必须抛出throws RemoteException异常
* @return
* @throws RemoteException
*/
public String getLocation() throws RemoteException;
public int getCount() throws RemoteException;
public String getDescription() throws RemoteException;
public State getCurrState() throws RemoteException;
}
package com.undergrowth.proxy;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* 远程服务对象
* @author Administrator
*
*/
public class GumballMachine extends UnicastRemoteObject implements
GumballMachineRemote {
String location;
String description;
int count;
State currentState;
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 因为UnicastRemoteObject构造器需要处理异常 因为RMI在网络上传输 会发生未知的异常
*
* @throws RemoteException
*/
protected GumballMachine() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
public GumballMachine(String location, String description, int count) throws RemoteException {
super();
this.location = location;
this.description = description;
this.count = count;
if(count>0){
this.currentState = new NoMoneyState();
}
}
@Override
public String getLocation() {
// TODO Auto-generated method stub
return location;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return count;
}
@Override
public String getDescription() {
// TODO Auto-generated method stub
return description;
}
@Override
public State getCurrState() {
// TODO Auto-generated method stub
return currentState;
}
}
相关状态
package com.undergrowth.proxy;
import java.io.Serializable;
/**
* 使用RMI传输State
* @author Administrator
*
*/
public interface State extends Serializable{
public void insertMoney();
}
无币状态
package com.undergrowth.proxy;
/**
* 模拟初始状态
* @author Administrator
*
*/
public class NoMoneyState implements State {
@Override
public void insertMoney() {
// TODO Auto-generated method stub
System.out.println("投币");
}
}
RMI注册服务和查找
package com.undergrowth.proxy;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
/**
* RMI注册服务和查找
* @author Administrator
*
*/
public class RegisterRmiServer {
public static void registerRmi(int port,String name,GumballMachineRemote remoteServer){
try {
//创建register端口监听
LocateRegistry.createRegistry(port);
//绑定服务
Naming.rebind(name, remoteServer);
//注册远程服务成功
System.out.println("注册远程服务成功");
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static GumballMachineRemote getRmiServer(String name){
try {
return (GumballMachineRemote) Naming.lookup(name);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
测试类
package com.undergrowth.proxy.test;
import static org.junit.Assert.*;
import java.rmi.RemoteException;
import javax.imageio.spi.RegisterableService;
import org.junit.Test;
import com.undergrowth.proxy.GumballMachine;
import com.undergrowth.proxy.GumballMachineRemote;
import com.undergrowth.proxy.RegisterRmiServer;
public class GumballMachineRemoteTest {
@Test
public void test() {
try {
//创建远程服务
GumballMachineRemote remoteServer=new GumballMachine("广州萝岗", "科学大道高德汇", 100);
//绑定
int port=4567;
RegisterRmiServer.registerRmi(port,"rmi://192.168.1.101:"+port+"/remoteServer", remoteServer);
//等待客户端的查找RMI服务
while(true){
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Test
public void testClient(){
int port=4567;
GumballMachineRemote remoteServer=RegisterRmiServer.getRmiServer("rmi://192.168.1.101:"+port+"/remoteServer");
try {
System.out.println(remoteServer.getCount());
System.out.println(remoteServer.getLocation());
System.out.println(remoteServer.getDescription());
System.out.println(remoteServer.getCurrState());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
先test(),然后testClient()
查看服务端口
控制台
100
广州萝岗
科学大道高德汇
com.undergrowth.proxy.NoMoneyState@193a6a5
2、虚拟代理,使用JFRAME加载图片组件,加载网络资源,使用状态模式管理图片的状态
面板
package com.undergrowth.proxy;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
/**
* 虚拟代理-->用于代理大开销的资源
* 使用代理 在未加载资源时,显示提示信息
* @author Administrator
*
*/
public class LoadImageUrlFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
JMenu menu;
JMenuBar menuBar;
Map<String, String> imageResources = new HashMap<String, String>();
ImageComponent imageComponent;
public LoadImageUrlFrame() {
initResources();
menu = new JMenu("加载图片");
//添加菜单项
addMenuItem(menu);
menuBar = new JMenuBar();
menuBar.add(menu);
setJMenuBar(menuBar);
//初始化图片
Icon icon=null;
try {
icon = new ImageProxy(new URL(imageResources.get("熊黛林")));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//添加图片组件
imageComponent=new ImageComponent(icon);
getContentPane().add(imageComponent);
// 初始化操作
setSize(800, 500);
setLocation((getToolkit().getScreenSize().width-getWidth())/2, (getToolkit().getScreenSize().height-getHeight())/2);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
/**
* 添加菜单项
* @param menu2
*/
private void addMenuItem(JMenu menu2) {
// TODO Auto-generated method stub
for (Iterator iterator = imageResources.keySet().iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
//添加菜单项
JMenuItem menuItem=new JMenuItem(name);
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
//当点击菜单项的时候
//替换图片组件中的图片 并将frame重绘
try {
//替换图像组件中的图片
imageComponent.setIcon(new ImageProxy(new URL(imageResources.get(e.getActionCommand()))));
//重绘面板
repaint();
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
menu2.add(menuItem);
}
}
/**
* 初始化图片资源
*/
private void initResources() {
// TODO Auto-generated method stub
imageResources
.put("古力娜扎",
"http://cdn.duitang.com/uploads/item/201207/27/20120727130449_hSxQk.jpeg");
imageResources.put("熊黛林",
"http://ent.shangdu.com/stardata/P_5962597_1__1869907784.jpg");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
LoadImageUrlFrame frame = new LoadImageUrlFrame();
}
}
图片组件
package com.undergrowth.proxy;
import java.awt.Graphics;
import javax.swing.Icon;
import javax.swing.JComponent;
public class ImageComponent extends JComponent {
/**
*
*/
private static final long serialVersionUID = 1L;
Icon icon;
public ImageComponent(Icon icon){
this.icon=icon;
}
/**
* 绘制图片组件
*/
@Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
int x=icon.getIconWidth();
int y=icon.getIconHeight();
x=(800-x)/2;
y=(500-y)/2;
icon.paintIcon(this, g, x, y);
}
public void setIcon(Icon icon) {
this.icon = icon;
}
}
图片代理
package com.undergrowth.proxy;
import java.awt.Component;
import java.awt.Graphics;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
public class ImageProxy implements Icon {
ImageIcon icon;
//图像的状态 使用状态模式 在加载与未加载之间切换
ImageState imageLoadState;
ImageState imageNonLoadState;
ImageState imageCurr;
//代理图片的位置
URL imageUrl;
public ImageProxy(URL imageUrl){
this.imageUrl=imageUrl;
imageNonLoadState=new ImageNonLoadState(this);
imageLoadState=new ImageLoadState(this);
imageCurr=imageNonLoadState;
}
/**
* 委托给当前状态进行处理
*/
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
// TODO Auto-generated method stub
imageCurr.paintIcon(c, g, x, y);
}
@Override
public int getIconWidth() {
// TODO Auto-generated method stub
return imageCurr.getIconWidth();
}
@Override
public int getIconHeight() {
// TODO Auto-generated method stub
return imageCurr.getIconHeight();
}
public ImageState getImageCurr() {
return imageCurr;
}
public void setImageCurr(ImageState imageCurr) {
this.imageCurr = imageCurr;
}
public ImageState getImageLoadState() {
return imageLoadState;
}
public ImageState getImageNonLoadState() {
return imageNonLoadState;
}
public ImageIcon getIcon() {
return icon;
}
public void setIcon(ImageIcon icon) {
this.icon = icon;
}
public URL getImageUrl() {
return imageUrl;
}
}
图片状态接口
package com.undergrowth.proxy;
import javax.swing.Icon;
/**
* 图像状态接口
* @author Administrator
*
*/
public interface ImageState extends Icon{
}
图片已加载状态
package com.undergrowth.proxy;
import java.awt.Component;
import java.awt.Graphics;
public class ImageLoadState implements ImageState {
ImageProxy imageProxy;
public ImageLoadState(ImageProxy imageProxy) {
super();
this.imageProxy = imageProxy;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
// TODO Auto-generated method stub
imageProxy.getIcon().paintIcon(c, g, x, y);
}
@Override
public int getIconWidth() {
// TODO Auto-generated method stub
return imageProxy.getIcon().getIconWidth();
}
@Override
public int getIconHeight() {
// TODO Auto-generated method stub
return imageProxy.getIcon().getIconHeight();
}
}
图片未加载状态
package com.undergrowth.proxy;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.ImageIcon;
public class ImageNonLoadState implements ImageState {
ImageProxy imageProxy;
public ImageNonLoadState(ImageProxy imageProxy){
this.imageProxy=imageProxy;
}
@Override
public void paintIcon(final Component c, Graphics g, int x, int y) {
// TODO Auto-generated method stub
g.drawString("正在加载图片中。。。", x, y);
//使用线程 加载网络资源 加载完成后 重绘面板
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//修改图片状态
imageProxy.setIcon(new ImageIcon(imageProxy.getImageUrl()));
imageProxy.setImageCurr(imageProxy.getImageLoadState());
//重绘
c.repaint();
}
}).start();
}
@Override
public int getIconWidth() {
// TODO Auto-generated method stub
return 400;
}
@Override
public int getIconHeight() {
// TODO Auto-generated method stub
return 400;
}
}
测试 运行面板
3、保护代理,用于控制权限访问
代理者与被代理者的共同接口
package com.undergrowth.proxy;
/**
* Person接口 用于代理和被代理的共同接口
* 用于实例保护代理
* @author Administrator
*
*/
public interface Person {
public String getName() ;
public void setName(String name) ;
public String getHobby();
public void setHobby(String hobby) ;
public String getDescription() ;
public void setDescription(String description);
public float getScore() ;
public void setScore(float score) ;
}
被代理者
package com.undergrowth.proxy;
/**
* 每个人都可以维护自己的信息 但是评分不能自己维护 需要别人维护
* @author Administrator
*
*/
public class PersonBeanImpl implements Person{
String name;
String hobby;
String description;
float score;
public PersonBeanImpl(String name, String hobby, String description) {
super();
this.name = name;
this.hobby = hobby;
this.description = description;
this.score = 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
@Override
public String toString() {
return "PersonBean [name=" + name + ", hobby=" + hobby
+ ", description=" + description + ", score=" + score + "]";
}
}
代理工厂
package com.undergrowth.proxy;
import java.lang.reflect.Proxy;
/**
* 简单工厂
* 利用JDK内置的代理 创建代理对象
* @author Administrator
*
*/
public class ProxyFactory {
public static Person getOwnerPersonBean(Person personBean){
return (Person) Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(), new PersonBeanOwnerHandler(personBean));
}
public static Person getNonOwnerPersonBean(Person personBean){
return (Person) Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(), new PersonBeanNonOwnerHandler(personBean));
}
}
拥有者,事件处理者
package com.undergrowth.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 自己处理器(拥有者) 自己可以维护自己的信息 除了评分以外
* @author Administrator
*
*/
public class PersonBeanOwnerHandler implements InvocationHandler {
Person personBean;
public PersonBeanOwnerHandler(Person personBean) {
super();
this.personBean = personBean;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
if(method.getName().startsWith("get")){//获取自己的其他信息
return method.invoke(personBean, args);
}else if(method.getName().equals("setScore")){
throw new IllegalAccessException("你不能自己给自己评分");
}else if(method.getName().startsWith("set")){ //设置自己的其他信息
return method.invoke(personBean, args);
}
return null;
}
}
非拥有者
package com.undergrowth.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 不是自己处理器(非拥有者) 可以获取信息 可以设置其他人的评分 但是不能设置其他人的其他信息
* @author Administrator
*
*/
public class PersonBeanNonOwnerHandler implements InvocationHandler {
Person personBean;
public PersonBeanNonOwnerHandler(Person personBean) {
super();
this.personBean = personBean;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
if(method.getName().startsWith("get")){
return method.invoke(personBean, args);
}else if (method.getName().equals("setScore")) {
return method.invoke(personBean, args);
}else if (method.getName().startsWith("set")) {
throw new IllegalAccessException("你不能设置其他人的其他信息");
}
return null;
}
}
测试
package com.undergrowth.proxy.test;
import static org.junit.Assert.*;
import java.lang.reflect.InvocationHandler;
import org.junit.Test;
import com.undergrowth.proxy.Person;
import com.undergrowth.proxy.PersonBeanImpl;
import com.undergrowth.proxy.PersonBeanOwnerHandler;
import com.undergrowth.proxy.ProxyFactory;
public class PersonBeanTest {
@Test
public void test() {
PersonBeanImpl personBean = new PersonBeanImpl("科比", "篮球", "职业素养最好的运动员");
System.out.println(personBean);
//创建拥有者
Person personBeanOwner = ProxyFactory.getOwnerPersonBean(personBean);
System.out.println(personBeanOwner.getName());
personBeanOwner.setDescription(personBeanOwner.getDescription()
+ ",老将中的战斗机");
System.out.println(personBeanOwner.getDescription());
System.out.println(personBean);
try {
// 自己给自己评分 会发生异常
personBeanOwner.setScore(100);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.println(personBean);
}
//创建非拥有者
Person personNonOwner=ProxyFactory.getNonOwnerPersonBean(personBean);
System.out.println(personNonOwner.getDescription());
personNonOwner.setScore(100);
System.out.println(personBean);
try {
//设置别人的信息 会发生异常
personNonOwner.setDescription("足球踢得非常好");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.println(personBean);
}
}
}
控制台
PersonBean [name=科比, hobby=篮球, description=职业素养最好的运动员, score=0.0]
java.lang.reflect.UndeclaredThrowableException
at $Proxy4.setScore(Unknown Source)
at com.undergrowth.proxy.test.PersonBeanTest.test(PersonBeanTest.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
科比
职业素养最好的运动员,老将中的战斗机
PersonBean [name=科比, hobby=篮球, description=职业素养最好的运动员,老将中的战斗机, score=0.0]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.IllegalAccessException: 你不能自己给自己评分
at com.undergrowth.proxy.PersonBeanOwnerHandler.invoke(PersonBeanOwnerHandler.java:29)
... 25 more
PersonBean [name=科比, hobby=篮球, description=职业素养最好的运动员,老将中的战斗机, score=0.0]
职业素养最好的运动员,老将中的战斗机
PersonBean [name=科比, hobby=篮球, description=职业素养最好的运动员,老将中的战斗机, score=100.0]
java.lang.reflect.UndeclaredThrowableException
at $Proxy4.setDescription(Unknown Source)
at com.undergrowth.proxy.test.PersonBeanTest.test(PersonBeanTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.IllegalAccessException: 你不能设置其他人的其他信息
at com.undergrowth.proxy.PersonBeanNonOwnerHandler.invoke(PersonBeanNonOwnerHandler.java:31)
... 25 more
PersonBean [name=科比, hobby=篮球, description=职业素养最好的运动员,老将中的战斗机, score=100.0]
以上即是远程代理、虚拟代理、保护代理的示例代码,代理模式的应用点太多了,后续遇到或者学习到,持续更新中,记录学习的脚步