在代理模式(Proxy Pattern)中,一个类代表另一个类的功能,这种类型属于结构性模式。
在代理模式中,创建现有对象的对象,以便向外界提供功能接口。
为其他对象提供一种以控制这个对象的访问。
在直接访问对象时带来的问题,比如说:要访问的对象在远程机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
想在访问一个类时做一些控制
增加中间层
实现与代理类的组合
1.windows快捷方式2.spring aop
1.职责清晰2.高扩展性3.智能化
1.由于在客户端和真实性主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢2.实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
按职责来划分,通常有以下使用场景:
1.远程代理,2.虚拟代理3.Copy-on-Write代理4.保护(Protect or Access)代理5.Cache代理6.防火墙代理7.同步化代理8.只能引用代理
1.和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口2.和装饰器模式的区别:装饰器模式是为了增强功能,而代理模式是为了加以控制。
jdk动态代理,直接上代码
定义一个被代理类的接口,代理对象和被代理对象时兄弟关系
package com.jdkproxy.$interface;
public interface Subject {
int sellBooks();
String speak();
}
package com.jdkproxy.$interface.impl;
import com.jdkproxy.$interface.Subject;
public class RealSubject implements Subject{
@Override
public int sellBooks() {
System.out.println("sell books");
return 1;
}
@Override
public String speak() {
System.out.println("speak");
return "zhangsan";
}
}
package com.jdkproxy.handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.jdkproxy.$interface.Subject;
public class InvocationHandlerDemo implements InvocationHandler{
//因为需要处理真是角色,需要传进来
private Subject realSubject;
public InvocationHandlerDemo(Subject realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy class");
if(method.getName().equals("sellBooks")){
int param = (int) method.invoke(realSubject,args);
System.out.println("sell books");
return param;
}else if(method.getName().equals("speak")){
String param2 = (String) method.invoke(realSubject,args);
return param2;
}
return null;
}
}
package com.jdkproxy.test;
import java.lang.reflect.Proxy;
import org.junit.Test;
import com.jdkproxy.$interface.Subject;
import com.jdkproxy.$interface.impl.RealSubject;
import com.jdkproxy.handler.InvocationHandlerDemo;
public class TestDemo {
@Test
public void test(){
Subject subject = new RealSubject();
InvocationHandlerDemo invocation = new InvocationHandlerDemo(subject);
Subject proxy = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{Subject.class},invocation);
proxy.sellBooks();
proxy.speak();
}
}
Cglib 动态代理是针对代理的类, 动态生成一个子类, 然后子类覆盖代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。
CGLIB作为一个开源项目,其代码托管在github,地址为:https://github.com/cglib/cglib
public class Engineer {
public void eat(){
System.out.println("engineer is eatting");
}
public final void work(){
System.out.println("engineer is working");
}
private void play(){
System.out.println("enginner is playing");
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Object obj;
public CglibProxy(Object obj) {
this.obj = obj;
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("before invocation");
Object result = arg1.invoke(obj,arg2);
System.out.println("after invocation");
return result;
}
public static Object getProxy(Object obj){
Enhancer e = new Enhancer();
e.setSuperclass(obj.getClass());
e.setCallback(new CglibProxy(obj));
return e.create();
}
}
import org.junit.Test;
public class TestDemo1 {
@Test
public void test(){
Engineer engineer = (Engineer) CglibProxy.getProxy(new Engineer());
engineer.eat();
engineer.work();
}
}
before invocation
engineer is eatting
after invocation
engineer is working