代理模式真得这么简单
代理模式的定义:为另一个对象提供一个替身或占位符以控制对这个对象的访问
代理模式类图
简单描述就是真实对象,RealSubject
,和代理对象,Proxy
实现同一个接口Subject
,并且代理对象Proxy
持有真实对象的引用
静态代理实例
GumballMachine
,作为真实对象
//糖果机,拥有两个属性,位置和糖果数量
public class GumballMachine{
String location;
int count;
public GumballMachine(String location, int count){
this.location = location;]
this.count = count;
}
public String getLocation(){return location;}
public int getCount(){;return count;}
}
GumballMonitor
,作为代理对象,控制对真实对象的访问
public class GumballMonitor{
GumballMachine machine;
public GumballMonitor(GumballMachine machine){
this.machine = machine;
}
public void report() {
System.out.println("Gumball Machine " + machine.getLocation());
System.out.println("Current inventory: " + machine.getCount() + "gumballs");
}
}
Main函数
public class GumballMachineTestDrive{
public static void main(String args[]) {
GumballMachine machine = new GumballMachine("ChangJinag", 20);
GumballMonitor monitor = new GumballMonitor(machine);
monitor.report();
}
}
动态代理实例
java动态代理工具,在java.lang.reflect包里,使用起来其实也简单,下面用一个实例简单介绍一下java动态代理的具体用法
java动态代理类图
真实对象RealSubject
,和代理对象,Proxy
,实现共同接口,Proxy
对象持有InvocationHanlder
引用,InvocationHandler
同时持有真实对象的引用。
所以对代理方法的访问,会转接到InvocationHandler
类的invoke方法上,invoke方法又会主动调用RealSubect
相应方法。
案例
有一个Person类,除了维护个人信息之外,还拥有一个
HotOrNotRating
属性(评分属性)此属性本人不能修改,只能由他人进行修改。所以需要控制对此属性的访问。
Person和其代理共同实现的接口类
interface PersonBean{
void setName(String name);
void setAge(int age);
void setHotOrNotRating(int HotOrNotRating);
String getName();
int getAge();
int getHotOrNotRating();
}
Person类
class Person implements PersonBean{
String name;
int age;
int HotOrNotRating;
Person(){}
Person(String name, int age, int HotOrNotRating){
this.name = name; this.age = age;
this.HotOrNotRating = HotOrNotRating;
}
public void setName(String name){this.name = name;}
public void setAge(int age){this.age = age;}
public void setHotOrNotRating(int HotOrNotRating){
this.HotOrNotRating = HotOrNotRating;
}
public String getName() {return name;}
public int getAge() {return age;}
public int getHotOrNotRating() {return HotOrNotRating;}
}
OwnerInvocationHandler类
class OwnerInvocationHandler implements InvocationHandler{
PersonBean person;
public OwnerInvocationHandler(PersonBean person) {
this.person = person;
}
public Object invoke(Object proxy, Method method, Object[]args) throws IllegalAccessException{
try{
if(method.getName().startsWith("set")){
if(method.getName().startsWith("setHotOrNotRating"))
throw new IllegalAccessException();
else return method.invoke(person, args);
}else return method.invoke(person,args);
}catch(InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
Main类
public class Main{
//动态生成代理
public static PersonBean getOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}
public static void main(String args[]){
PersonBean person = new Person("Bob", 24, 90);
PersonBean ownerProxy = getOwnerProxy(person);
try{
ownerProxy.setHotOrNotRating(10);
}catch(Exception e) {
System.out.println("Owner can't modify the field of HotOrNotRating");
}
}
}
CGLIB代理实例
person类:与上同
实现MethodInterceptor接口,方法调用均会被intercept
方法拦截
/**
sub:生成的代理对象
method:真实对象原方法
objectArr:方法参数列表
methodProxy:代理方法
**/
class MethodInterceptorImp implements MethodInterceptor{
@Override
public Object intercept(Object sub, Method method, Object[] objectArr, MethodProxy methodProxy)throws Throwable {
System.out.println("代理Start");
Object object = methodProxy.invokeSuper(sub, objectArr);
System.out.println("代理End");
return object;
}
}
Main方法
public class Main {
public static void main(String args[]) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Person.class);
enhancer.setCallback(new MethodInterceptorImp());
Person proxy = (Person)enhancer.create();
proxy.setName("zhouyu");
System.out.println(proxy.getName());
}
}
//代理Start
//代理End
//代理Start
//代理End
//zhouyu