Proxy Pattern
代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标之间起到中介的作用。
举个例子:
我想买一台lenovo的电脑,我去总部去买,可是人家不卖给我,于是我找到了联想的代理,从代理那里买到了一台电脑,我知道,他们肯定加价了!
上面的例子就是一个简单的代理模式,我不能直接去总部买,但是我可以通过代理去买,通过代理的一个缺点就是代理会给你加上一些额外的金钱或者其他的内容。
代理模式一般涉及到三个角色:
抽象角色:声明真实对象和代理对象的共同接口;(比如卖电脑这个接口)
真实角色:代理角色所代表的的真实对象,是我们最终要引用的对象;
代理角色:代理对象角色内部包含对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口(卖电脑)以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作(比如加价),相当于对真实对象进行封装。
下面以买lenovo电脑为例
package com.pattern.proxy;
public interface Sales {
public void sale();//无论是lenovo公司还是代理,都是要卖产品的
}
package com.pattern.proxy;
public class Lenovo implements Sales{
@Override
public void sale() {
System.out.println("Lenovo sale...");//这是让代理来请求的,个人用户不能直接来(人为规定)
}
}
package com.pattern.proxy;
public class Proxy implements Sales{
private Sales sale;//代理的产品,可以选择lenovo作为代理的产品
public Proxy(Sales sale){
this.sale=sale;
}
@Override
public void sale() {
sale.sale();//调用真实对象的方法
}
}
package com.pattern.proxy;
public class Test {
public static void main(String[] args) {
Lenovo l=new Lenovo();//联想公司
Sales s=new Proxy(l);//代理商s代理了联想公司l
s.sale();//向代理s买了一台联想电脑:Lenovo sale...
}
}
使用代理模式的最大好处就是可以在真实对象请求的前后可以加入特有的操作:
package com.pattern.proxy1;
public class Proxy implements Sales{
private Sales sale;//代理的产品,可以选择lenovo作为代理的产品
public Proxy(Sales sale){
this.sale=sale;
}
@Override
public void sale() {
System.out.println("before sale...");
sale.sale();//调用真实对象的方法
System.out.println("after sale...");
}
}
动态代理
Java提供的动态代理(被代理对象必须有接口)
cglib提供动态代理(创建被代理对象的子类)
AOP的核心就是动态代理,如果存在接口则使用Java,否则使用cglib去实现动态代理;
package com.pattern.proxy2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
private Object obj;
public MyInvocationHandler(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("invoke before...");
Object result=method.invoke(obj, args);//被代理对象方法的执行
System.out.println("invoke after...");
return result;
}
}
package com.pattern.proxy2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
Lenovo l=new Lenovo();
InvocationHandler invocationHandler=new MyInvocationHandler(l);//动态代理联想
//创建联想的代理对象lenovoSale
Sales lenovoSale=(Sales) Proxy.newProxyInstance(l.getClass().getClassLoader(), l.getClass().getInterfaces(), invocationHandler);
lenovoSale.sale();
}
}
缺点:如果一个类没有接口,则不能使用Java中的动态代理!
使用OOP中的继承关系,实现代理模式:
package com.pattern.proxy3;
public class Person {
public void sayHello(){
System.out.println("hello,person...");
}
}
package com.pattern.proxy3;
public class PersonSon extends Person{
@Override
public void sayHello() {
System.out.println("before...");
super.sayHello();
System.out.println("after...");
}
}
package com.pattern.proxy3;
public class Test {
public static void main(String[] args) {
Person p=new PersonSon();
p.sayHello();
}
}
cglib(asm原理的简化)提供代理(动态产生被代理对象的子类)
hibernate,spring里都用到的包
添加jar包!!spring里的lib中含有cglib
package com.pattern.proxy4;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MyMethodInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("cglib before...");
Object result=methodProxy.invokeSuper(obj, args);
System.out.println("cglib after...");
return result;
}
}
package com.pattern.proxy4;
public class Person {
public void sayHello(){
System.out.println("hello....");
}
}
package com.pattern.proxy4;
import net.sf.cglib.proxy.Enhancer;
public class Test {
public static void main(String[] args) {
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(Person.class);
enhancer.setCallback(new MyMethodInterceptor());
Person p=(Person) enhancer.create();
p.sayHello();
}
}