`
lovnet
  • 浏览: 6707541 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

静态代理(static proxy)和动态代理(dynamic proxy)

 
阅读更多
两种类型AOP:静态AOP和动态AOP。

静态代理:
代理对象与被代理对象必须实现同一个接口。

demo:
  1. packagecn.partner4java.proxy.staticproxy;
  2. /**
  3. * 静态代理,统一接口
  4. * @author partner4java
  5. *
  6. */
  7. publicinterfaceIHello {
  8. /**
  9. * 可以带来的统一方法
  10. * @param name
  11. */
  12. publicvoidhello(String name);
  13. }
  1. packagecn.partner4java.proxy.staticproxy;
  2. /**
  3. * 被代理的对象,需要借助代理对象加入日志
  4. * @author partner4java
  5. *
  6. */
  7. publicclassHelloSpeakerimplementsIHello {
  8. publicvoidhello(String name) {
  9. System.out.println("Hello "+ name);
  10. }
  11. }
  1. packagecn.partner4java.proxy.staticproxy;
  2. /**
  3. * 代理对象,给被代理对象添加日志
  4. */
  5. publicclassHelloProxyimplementsIHello {
  6. privateIHello iHello;
  7. publicHelloProxy(IHello iHello) {
  8. super();
  9. this.iHello = iHello;
  10. }
  11. publicvoidhello(String name) {
  12. System.out.println("记录日志");
  13. iHello.hello(name);
  14. }
  15. }
  1. packagecn.partner4java.proxy.staticproxy;
  2. /**
  3. * 调用
  4. * @author partner4java
  5. *
  6. */
  7. publicclassProxyDemo {
  8. publicstaticvoidmain(String[] args) {
  9. IHello iHello =newHelloProxy(newHelloSpeaker());
  10. iHello.hello("long");
  11. }
  12. }





动态代理:
动态代理区别于静态带来实现的地方在于织入过程是在运行时动态进行的。自己实现一般实现java.lang.reflect.InvocationHandler接口。
例子:
  1. packagecn.partner4java.proxy.dynamicproxy;
  2. publicinterfaceIHello {
  3. publicvoidhello(String name);
  4. }
  1. packagecn.partner4java.proxy.dynamicproxy;
  2. /**
  3. * 被代理的对象,需要借助代理对象加入日志
  4. * @author partner4java
  5. *
  6. */
  7. publicclassHelloSpeakerimplementsIHello {
  8. publicvoidhello(String name) {
  9. System.out.println("Hello "+ name);
  10. }
  11. }
  1. packagecn.partner4java.proxy.dynamicproxy;
  2. importjava.lang.reflect.InvocationHandler;
  3. importjava.lang.reflect.Method;
  4. importjava.lang.reflect.Proxy;
  5. /**
  6. * 动态代理对象
  7. * @author partner4java
  8. *
  9. */
  10. publicclassLogHandlerimplementsInvocationHandler {
  11. privateObject delegate;
  12. publicObject bind(Object delegate){
  13. this.delegate = delegate;
  14. returnProxy.newProxyInstance(delegate.getClass().getClassLoader(),
  15. delegate.getClass().getInterfaces(),this);
  16. }
  17. /**
  18. * 代理对象,这里面还可以改变原有的方法
  19. */
  20. publicObject invoke(Object proxy, Method method, Object[] args)
  21. throwsThrowable {
  22. Object result =null;
  23. try{
  24. System.out.println("添加日志");
  25. result = method.invoke(delegate, args);
  26. }catch(Exception e) {
  27. e.printStackTrace();
  28. }
  29. returnnull;
  30. }
  31. }
  1. packagecn.partner4java.proxy.dynamicproxy;
  2. /**
  3. * 测试
  4. * @author partner4java
  5. *
  6. */
  7. publicclassProxyDemo {
  8. publicstaticvoidmain(String[] args) {
  9. LogHandler logHandler =newLogHandler();
  10. IHello iHello = (IHello) logHandler.bind(newHelloSpeaker());
  11. iHello.hello("long");
  12. }
  13. }


------------------------------------------------------------------


利用ProxyFactory连接CGLIB简单实现AOP:
加入包aopalliance.jar\cglib-nodep-2.1_3.jar
demo:
  1. packagecn.partner4java.proxy.proxyfactory;
  2. /**
  3. * 被代理的对象
  4. * @author partner4java
  5. *
  6. */
  7. publicclassMessageWriter {
  8. publicvoidwriteMessage(){
  9. System.out.println("world!");
  10. }
  11. }
  1. packagecn.partner4java.proxy.proxyfactory;
  2. importorg.aopalliance.intercept.MethodInterceptor;
  3. importorg.aopalliance.intercept.MethodInvocation;
  4. /**
  5. * 装饰者<br/>
  6. * MethodInterceptor接口是对方法调用连接点实现包围通知的AOP联盟标准接口
  7. * @author partner4java
  8. *
  9. */
  10. publicclassMessageDecoratorimplementsMethodInterceptor{
  11. publicObject invoke(MethodInvocation invocation)throwsThrowable {
  12. System.out.print("Hello ");
  13. Object retVal = invocation.proceed();
  14. returnretVal;
  15. }
  16. }
  1. packagecn.partner4java.proxy.proxyfactory;
  2. importorg.springframework.aop.framework.ProxyFactory;
  3. /**
  4. * 调用组装
  5. * 这里最重要的部分是我们使用ProxyFactory来创建一个目标对象代理,同时织入通知
  6. * @author partner4java
  7. *
  8. */
  9. publicclassHelloWorldWeaver {
  10. publicstaticvoidmain(String[] args) {
  11. //目标
  12. MessageWriter target =newMessageWriter();
  13. //create the proxy
  14. ProxyFactory proxyFactory =newProxyFactory();
  15. proxyFactory.addAdvice(newMessageDecorator());
  16. proxyFactory.setTarget(target);
  17. //获取返回被代理的目标
  18. MessageWriter proxy = (MessageWriter) proxyFactory.getProxy();
  19. target.writeMessage();
  20. System.out.println("---");
  21. proxy.writeMessage();
  22. //后台打印:
  23. //world!
  24. //---
  25. //World world!
  26. }
  27. }







------------------------------------------------------------------

代理
1.代理解决什么问题,为已存在的目标类的方法增加一些系统功能。如果采用工厂模式和配置文件进行管理,以后也很容易就可以去掉增加的功能。
2.静态代理类的工作原理,太多静态代理类,还有什么意思?jvm可以帮我们创建代理类,这就是动态代理类。
3.让jvm创建动态代理类,我们需要给它提供哪些信息?
让jvm帮我们创建一个类,我们需要为它提供哪些信息呢?a.有哪些方法,即告诉它实现哪些接口;b.产生的类必须有个妈妈,即类加载器对象;c.它生成的类中的方法的代码是怎样的,需我告诉它,我把我的代码写在一个约定好了接口的对象的方法中,把对象传给它,它调用我的方法,即相当于插入了我的代码。
4.写程序的步骤:
1). 快速演示动态代理的效果
  1. privatestaticvoidtest1() {
  2. Collection proxy = (Collection)Proxy.newProxyInstance(
  3. ProxyTest.class.getClassLoader(),//first parameter
  4. newClass[]{Collection.class} ,//second parameter
  5. newInvocationHandler(){//third parameter
  6. Vector target =newVector();
  7. @Override
  8. publicObject invoke(Object proxy, Method method,
  9. Object[] args)throwsThrowable {
  10. // TODO Auto-generated method stub
  11. System.out.println("begin "+ method.getName());
  12. Object retval = method.invoke(target, args);
  13. System.out.println("end"+ method.getName());
  14. returnretval;
  15. }
  16. }
  17. );
  18. //---
  19. System.out.println(proxy.getClass().getName());
  20. proxy.add("abc");
  21. proxy.add("xyz");
  22. System.out.println(proxy.size());
  23. //---
  24. }


2).可以接收外面传入的目标
  1. privatestaticvoidtest2() {
  2. Vector v =newVector();
  3. classMyInvocationHandlerimplementsInvocationHandler
  4. {
  5. Collection target =null;
  6. publicMyInvocationHandler(){}
  7. publicMyInvocationHandler(Collection target){this.target = target;}
  8. @Override
  9. publicObject invoke(Object proxy, Method method,
  10. Object[] args)throwsThrowable {
  11. // TODO Auto-generated method stub
  12. System.out.println("begin "+ method.getName());
  13. Object retval = method.invoke(target, args);
  14. System.out.println("end"+ method.getName());
  15. returnretval;
  16. }
  17. }
  18. Collection proxy1 = (Collection)Proxy.newProxyInstance(
  19. ProxyTest.class.getClassLoader(),
  20. newClass[]{Collection.class} ,
  21. newMyInvocationHandler(v));
  22. System.out.println(proxy1.getClass().getName());
  23. proxy1.add("abc");
  24. proxy1.add("xyz");
  25. System.out.println(proxy1.size());
  26. }

3).最优雅的方式,接收目标同时返回代理,让调用者更懒惰,更方便,调用者甚至不用接触任何代理的API。
  1. privatestaticvoidtest3() {
  2. Vector v =newVector();
  3. classMyInvocationHandlerimplementsInvocationHandler
  4. {
  5. Collection target =null;
  6. publicCollection bind(Collection target)
  7. {
  8. this.target = target;
  9. Collection proxy1 = (Collection)Proxy.newProxyInstance(
  10. ProxyTest.class.getClassLoader(),
  11. newClass[]{Collection.class} ,
  12. this);
  13. returnproxy1;
  14. }
  15. @Override
  16. publicObject invoke(Object proxy, Method method,
  17. Object[] args)throwsThrowable {
  18. // TODO Auto-generated method stub
  19. System.out.println("begin "+ method.getName());
  20. Object retval = method.invoke(target, args);
  21. System.out.println("end"+ method.getName());
  22. returnretval;
  23. }
  24. }
  25. MyInvocationHandler handler =newMyInvocationHandler();
  26. Collection proxy1 = handler.bind(v);
  27. System.out.println(proxy1.getClass().getName());
  28. proxy1.add("abc");
  29. proxy1.add("xyz");
  30. System.out.println(proxy1.size());
  31. }


一点小心得:静态方法中也可以定义内部类,只是内部类中不能方法外部类的成员变量。

  1. iterface Foo
  2. {
  3. doTest();
  4. }
  5. Class xxx = Proxy.getProxyClass(Foo.class.getClassLoader(),Class [] {Foo.class});
  6. Proxy方法自动生成一个类的字节码,这个自动生成的类实现了Foo接口(可以实现若干接口)。生成的类有Foo接口中的所有方法和一个如下形式的构造方法:
  7. Xxx
  8. {
  9. InvocationHandler handler;
  10. publicXxx(InvocationHandler handler)
  11. {
  12. this.handler = handler;
  13. }
  14. //生成的Foo接口中的方法的运行原理
  15. doTest()
  16. {
  17. handler.invoke(this,newMethod("doTest"),null)
  18. }
  19. }
  20. 创建代理类的实例对象的语法解释
  21. clsProxy.getConstructor(Class []{InvocationHandlre.class}).newInstance(xhandlder);
  22. Invocationhandler接口的实现示意:
  23. classMyInvocationHandler impments InvocationHandler
  24. {
  25. invoke(Object proxy,Method method,Object[] args)
  26. {
  27. log.info();
  28. Mehtod.invoke(yyy);
  29. }
  30. }

分享到:
评论

相关推荐

    java 静态代理和动态代理学习实例源码

    java static proxy dynamic proxy

    08spring4_dynamicproxy.rar

    package cn.sxt.dynamicproxy; import java.util.ArrayList; import java.util.List; import cn.sxt.service.UserService; import cn.sxt.service.UserServiceImpl; public class Client { public ...

    vs没报错leetcode报错-leetcode:leetcode

    basicKnowledge.dynamicProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /* * JDK 动态代理 * */ public class dynamicProxyUsingJDK { ...

    Java 高级特性.doc

    因为程序里面有个静态方法,如果导入import static java.lang.Integer.parseInt;这样的程序就可以运行了。 2.可变参数与for循环增强 这个是一般的用法: public static void loop(String[] args){ for(int i=0;i;i++...

    二十三种设计模式【PDF版】

    设计模式之 Proxy(代理) 以 Jive 为例,剖析代理模式在用户级别授权机制上的应用 设计模式之 Facade(门面?) 可扩展的使用 JDBC针对不同的数据库编程,Facade提供了一种灵活的实现. 设计模式之 Composite(组合) ...

    VMWARE NSX-T

    0 Logical Routers 38 4.2.3 Fully Distributed Two Tier Routing 39 4.3 Edge Node 41 4.3.1 Bare Metal Edge 42 4.3.2 VM Form Factor 46 4.3.3 Edge Cluster 48 4.4 Routing Capabilities 49 4.4.1 Static ...

    Professional.MFC.with.VC6

    Static Controls Dialog Data Exchange Data Exchange Code in Practice Data Validation Code with DDV_ Using ClassWizard Performing Cross-Edits About Live Edits Using Common Dialogs File Save and ...

    CISCO 技术大集合

    建立动态地址翻译 ip nat inside source {list {access-list-number | name} pool name [overload] | static local-ip global-ip} 指定内部和外部端口 ip nat {inside | outside} 如下图所示, 路由器的Ethernet ...

    +Flex+集成到+Java+EE+应用程序的最佳实践(完整源代码)

    通过 RemoteObject 进行调用虽然简单,但存在不少问题:首先,RemoteObject 是一个 Dynamic Class,Flex Builder 的编译器无法替我们检查参数类型和参数个数,这样,在编写 ActionScript 代码时极易出错。...

    将 Flex 集成到 Java EE 应用程序的最佳实践(完整源代码)

    BlazeDS 将读取 services-config.xml 配置文件,该配置文件又引用了 remoting-config.xml、proxy-config.xml 和 messaging-config.xml 这 3 个配置文件,所以,一共需要 4 个配置文件。 由于 BlazeDS 需要将 Java ...

    ORACLE OSB开发指南

    Creating Proxy Server Resources..................................................................................................... 2-5 Creating Message Format Files ....................................

    VB.NET Developer's Guide(4574).pdf

    Dynamic Arrays 191 Functions 192 Object Oriented Programming 196 Inheritance 196 Polymorphism 197 Encapsulation 197 Classes 198 Adding Properties 198 Adding Methods 200 System.Object 201 ...

    php.ini-development

    ;;;;;;;;... 1.... 2.... 3.... 4.... 5.... 6.... The syntax of the file is extremely simple.... Section headers (e.g.... at runtime.... There is no name validation.... (e.g.... previously set variable or directive (e.g....

    spring-framework-reference4.1.4

    Instantiation with a static factory method .................................................... 30 Spring Framework 4.0.0.RELEASE Spring Framework Reference Documentation iii Instantiation using an ...

    spring-framework-reference-4.1.2

    Instantiation with a static factory method .................................................... 30 Spring Framework 4.0.0.RELEASE Spring Framework Reference Documentation iii Instantiation using an ...

Global site tag (gtag.js) - Google Analytics