1、动态代理的定义:为其他对象提供一个代理以控制对这个对象的访问

代理类主要负责委托类的预处理消息,过滤消息,把消息传给委托类以及消息事后处理

按照代理类的创建时期,代理类可以分为2种:静态代理类(在程序运行前代理类.class文件就以及生成)和动态代理类(字节码是在程序运行时由java反射机制动态生成)

静态代理的实例:

package com.vcredit.ddcash.decision;

public class ProxyTest {
public static void main(String[] args) {
HelloService helloService = new HelloServiceImpl();
HelloServiceProxy helloServiceProxy = new HelloServiceProxy(helloService);
helloServiceProxy.say();
}

}

interface HelloService{
void say();

}
class HelloServiceImpl implements HelloService{
public void say(){
System.out.println(11);
};

}
class HelloServiceProxy implements HelloService{
public HelloService helloService;
HelloServiceProxy(HelloService helloService){
this.helloService=helloService;
}
public void say(){
System.out.println("预处理");
helloService.say();//调用被代理的HellService的say方法
System.out.println("事后处理");
};
}

2、通过api看下proxy生成代理类的2中写法:

创建某一接口 Foo 的代理:

     InvocationHandler handler = new MyInvocationHandler(...);
Class proxyClass = Proxy.getProxyClass(
Foo.class.getClassLoader(), new Class[] { Foo.class });
Foo f = (Foo) proxyClass.
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });

或使用以下更简单的方法:

     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);
其实第二中写法就相当于对第一中写法的封装,具体看Proxy这个类;

3、具体实例:

public interface Subject  
{  
  public void doSomething();  
}  
public class RealSubject implements Subject  
{  
  public void doSomething()  
  {  
    System.out.println( "call doSomething()" );  
  }  
}  
public class ProxyHandler implements InvocationHandler  
{  
  private Object proxied;  
    
  public ProxyHandler( Object proxied )  
  {  
    this.proxied = proxied;  
  }  
    
  public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable  
  {  
    //在转调具体目标对象之前,可以执行一些功能处理

//转调具体目标对象的方法
    return method.invoke( proxied, args); 
   
    //在转调具体目标对象之后,可以执行一些功能处理
  }   
}

import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
import sun.misc.ProxyGenerator;  
import java.io.*;  
public class DynamicProxy  
{  
  public static void main( String args[] )  
  {  
    RealSubject real = new RealSubject();  
    Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
     new Class[]{Subject.class},
     new ProxyHandler(real));//要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
        
    proxySubject.doSomething();
  
    //write proxySubject class binary data to file  
    createProxyClassFile();  
  }  
    
  public static void createProxyClassFile()  
  {  
    String name = "ProxySubject";  
    byte[] data = ProxyGenerator.generateProxyClass( name, new Class[] { Subject.class } );  
    try 
    {  
      FileOutputStream out = new FileOutputStream( name + ".class" );  
      out.write( data );  
      out.close();  
    }  
    catch( Exception e )  
    {  
      e.printStackTrace();  
    }  
  }  
}

分析:当调用proxySubject.doSomething();时,就调用了$proxy0类中的doSomething()方法,在doSomething()方法中调用父类

proxy中h的invoke()方法,即InvercationHandler.invoke(),这个流程可以通过代理类的.class文件反编译后查看

部分截图:

public final void doSomething() {
   try {
   
super.h.invoke(this, m3, null);
    return;
   }
catch (Error e) {
   } catch (Throwable throwable)
{
    throw new
UndeclaredThrowableException(throwable);
   }
}

下面看下通过Proxy类的静态方法getProxyClass生成的class文件经过反编译后生成的代码:

public final class $Proxy0
extends Proxy
implements Subject{
---表名是一个最终类,此类继承了Proxy类,实现了Subject接口

public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

里面有一个带参数的构造方法,通过getProxyClass(...).getConstructor(parameterType p)//这个参数应该就是InvocationHandler这个接口类,从而通过super调用父类的带参构造器,从而给就有了InvocationHandler这个接口

protected Proxy(InvocationHandler h) {
 this.h = h;
    }

当调用$Proxy0类的doSomething()方法时:会调用h.invoke(...)方法

public final String doSomething() {
        try {
            return (String)this.h.invoke((Object)this, m3, new Object[]{});
        }
        catch (Error | RuntimeException v0) {
            throw v0;
        }
        catch (Throwable var2_2) {
            throw new UndeclaredThrowableException(var2_2);
        }
    }
看下invoke方法的3个参数 第一个指的就是被代理的类的实例也就是对应的RealSubject实例

m3指的是对应的方法

m3 = Class.forName("****.Subject").getMethod("doSomething");
第三个参数指的就是方法中的参数,没有参数就是null

再通过反射机制就可以唯一确定调用被代理类中的相关方法

4、Proxy已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy。Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。有很多条理由,人们可以否定对 class代理的必要性,但是同样有一些理由,相信支持class动态代理会更美好。接口和类的划分,本就不是很明显,只是到了Java中才变得如此的细化。如果只从方法的声明及是否被定义来考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。如此种种,不得不说是一个小小的遗憾。但是,不完美并不等于不伟大,伟大是一种本质,Java动态代理就是佐例。

Cglib动态代理 
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

还是举例说明:

public class BookImpl{//没有实现接口
 public void add(){
  System.out.println("这是一个新增的方法");
 }

}

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

//创建代理类,这个类实现MethodInterceptor接口
public class BookProxy  implements MethodInterceptor {

private Object target;
 
 public BookProxy(Object target){
  this.target=target;
 }
 
 @Override
 public Object intercept(Object arg0, Method arg1, Object[] arg2,
   MethodProxy arg3) throws Throwable {
  System.out.println("事务开始");
  Object result = arg3.invokeSuper(target, arg2);
  System.out.println("事务结束");
  return result;
 }

}

//测试类

public class TestCglib {
 public static void main(String[] args){
  
 BookImpl bi = new BookImpl();

BookProxy bp = new BookProxy(bi);
 BookImpl bii = (BookImpl)Enhancer.create(bi,bp);
  bii.add();
 }

}

//输出结果

事务开始
这是一个新增的方法
事务结束

java中的静态代理和动态代理的更多相关文章

  1. Java中的反射机制和动态代理

    一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...

  2. 【Java基础】java中的反射机制与动态代理

    一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...

  3. java中的静态分派和动态分派

    多态是java的基本特征之一,多态即一个对象具有多种形态(多种表达形式,猴子是动物的一种的表现形式),例如:子类是父类的一种形态. 当方法重载时,就会涉及到多态. 1:在重载时是通过参数的静态类型,而 ...

  4. java中静态代理,动态代理知识的补充

    文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...

  5. java中的静态代理和动态代理,入门整理

    静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...

  6. 017 Java中的静态代理、JDK动态代理、cglib动态代理

    一.静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由业务实现类.业务代理类两部分组成.业务实现类负责实现主要的业务方法,业 ...

  7. java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...

  8. java中静态代理和动态代理

    一.概述 代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象.如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目标对象功能 ...

  9. 一篇文章让你搞懂Java中的静态代理和动态代理

    什么是代理模式 代理模式是常用的java设计模式,在Java中我们通常会通过new一个对象再调用其对应的方法来访问我们需要的服务.代理模式则是通过创建代理类(proxy)的方式间接地来访问我们需要的服 ...

  10. Java中的代理模式--静态代理和动态代理本质理解

    代理模式定义:为其他对象提供了一种代理以控制对这个对象的访问. 代理模式的三种角色: Subject抽象主题角色:抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求. Real ...

随机推荐

  1. UVA - 1456 Cellular Network

    题目大意: 手机在蜂窝网络中的定位是一个基本问题.如果蜂窝网络已经得知手机处于c1, c2,-,cn这些区域中的一个.最简单的方法是同一时候在这些区域中寻找手机.但这样做非常浪费带宽. 因为蜂窝网络中 ...

  2. shell编程学习笔记(八):Shell中的if条件判断

    编程语言中都有条件判断,shell编程也不例外,下面我们来看一下shell中应该怎么使用if条件判断 以下蓝色字体部分为Linux命令,红色字体的内容为输出的内容: # cd /opt/scripts ...

  3. Windows 7安装Tensorflow

    以前是在Cent OS中运行Tensorflow,,经常需要切换操作系统,很不方便,于是决定在Windows 7下安装Tensorflow. 过程还是挺复杂的,需要安装的包括:Visual Studi ...

  4. Python import其他文件夹的文件

    一般情况下,import的文件和被import的文件在同一个路径下面,import也比较方便.如果这两个文件不在一个路径下面,import就比较麻烦了,需要在被import的文件路径下面新建一个__i ...

  5. 理解JAVA的IO

    1. 什么是流Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序列 ...

  6. 【Android】解析AccessibilityService(辅助服务)的使用

    辅助功能是Android系统提供的一种服务,派生自Service类.这个服务提供了增强的用户界面,目的是为了帮助残障人士.它一般提供了页面元素查找功能和元素点击功能. 通过辅助功能,开发者可以实现一些 ...

  7. springboot整合三 共享session,集成springsession

    官网介绍 - spring:session:https://docs.spring.io/spring-session/docs/current/reference/html5/ 1. Mave依赖 ...

  8. Redux 入门到高级教程

    Redux 是 JavaScript 状态容器,提供可预测化的状态管理. (如果你需要一个 WordPress 框架,请查看 Redux Framework.) Redux 除了和 React 一起用 ...

  9. replay的意义

    数据库重放: () 在测试环境中重新创建实际的生产数据库工作量. () 在生产中实施更改之前,确定和分析潜在的不稳定性. () 捕获生产中的工作量:

  10. c++ 条件变量

    .条件变量创建 静态创建:pthread_cond_t cond=PTHREAD_COND_INITIALIZER; 动态创建:pthread_cond _t cond; pthread_cond_i ...