结构型模式-----代理模式(Proxy)

时间:2022-10-01 07:35:10

1、代理模式

           为其他对象提供一种代理以控制对这个对象的访问。

 

    静态代理:(类似于装饰模式),在代理真实对象进行操作时,可以在操作之前与之后添加额外的操作。

 

      实例一:

 

   

public interface Sender {

public void send();

}
public class MailSender implements Sender {@Overridepublic void send() {System.out.println(" ~~~~ mailSender ~~~~ ");}}public class StaticProxy implements Sender {private MailSender sender = null;public StaticProxy(final MailSender sender) {this.sender = sender;}@Overridepublic void send() {System.out.println(" ~~~   before  send  ~~~~");this.sender.send();System.out.println(" ~~~~  after  send ~~~~~~");}}


       模拟测试:

 

     

public class Clinet {

public static void main(final String[] args) {
final StaticProxy sp = new StaticProxy(new MailSender());
sp.send();
}

}

 

     动态代理:(java从1.3开始引入动态代理,但他只能代码实现了一个或者多个接口的类,并不能直接对类进行动态代理)

 

public interface Sender {

public void send();

}

public class MailSender implements Sender {

@Override
public void send() {
System.out.println(" ~~~~ mailSender ~~~~ ");
}
}

public class DynamicProxy implements InvocationHandler {

private Object object = null;

public DynamicProxy(final Object object) {
this.object = object;
}

@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
System.out.println(" ~~~ before send ~~~~");
final Object obj = method.invoke(this.object, args);
System.out.println(" ~~~~ after send ~~~~~~");
return obj;
}
}

 

     模拟使用:

 

     

public static void main(final String[] args) {
final Sender sender = new SmsSender();
final InvocationHandler dp = new DynamicProxy(sender);

final Sender senderProxy = (Sender) Proxy.newProxyInstance(sender.getClass().getClassLoader(), sender
.getClass().getInterfaces(), dp);
senderProxy.send();
}


         动态代理扩展:如果想对类直接使用动态代理,可以使用CGLIB(Code Generation Library)包。

                  CGLIB是一个强大的高性能的代码生成包。它被许多AOP的框架(例如Spring AOP)使用,为他们提供方法的interception(拦截)。

                  Hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联。EasyMock通过使用模仿(moke)对象来测试java代码的包。

 

                  它们都通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。其原理是:生成一个要代理类的子类,子类覆盖要代理的类的所有不是final的方法。
             CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。

                   不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

 

   
        

 


cglib代码包结构
•core (核心代码) ◦EmitUtils
◦ReflectUtils
◦KeyFactory
◦ClassEmitter/CodeEmitter
◦NamingPolicy/DefaultNamingPolicy
◦GeneratorStrategy/DefaultGeneratorStrategy
◦DebuggingClassWriter
◦ClassGenerator/AbstractClassGenerator

•beans (bean操作类) ◦BeanCopier
◦BulkBean
◦BeanMap
◦ImmutableBean
◦BeanGenerator

•reflect ◦FastClass

•proxy ◦Enhancer
◦CallbackGenerator
◦Callback ■ MethodInterceptor , Dispatcher, LazyLoader , ProxyRefDispatcher , NoOp , FixedValue , InvocationHandler(提供和jdk proxy的功能)

◦CallbackFilter

•util ◦StringSwitcher
◦ParallelSorter

•transform

                      

            实例三、(实现对类的代理)

    

public class Temp {

public void temp() {
System.out.println(" ~~~ temp ~~~~~");
}

}

public class CglibProxy implements MethodInterceptor {

 public Object createProxy(final Object target) {
  final Enhancer enhancer = new Enhancer();
  // 设置代理目标
  enhancer.setSuperclass(target.getClass());
  // 设置回调
  enhancer.setCallback(this);
  enhancer.setClassLoader(target.getClass().getClassLoader());
  return enhancer.create();
 }

 

 /**
  * @param proxy
  *            代理类
  * @param method
  *            被代理的方法
  * @param params
  *            该方法的参数数组
  * @param methodproxy
  *            方法的代理
  */
 @Override
 public Object intercept(
   final Object proxy,
   final Method method,
   final Object[] params,
   final MethodProxy methodProxy) throws Throwable {
  System.out.println(" ~~~   before  send  ~~~~");
  final Object o = methodProxy.invokeSuper(proxy, params);
  System.out.println(" ~~~~  after  send ~~~~~~");
  return o;
 }
}

   

     模拟调用

  

public static void main(final String[] args) {
final Temp temp = new Temp();
final CglibProxy cp = new CglibProxy();
final Temp t1 = (Temp) cp.createProxy(temp);
t1.temp();
}