详解java中动态代理实现机制

代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

JAVA各种动态代理实现的比较

接口

interface AddInterface{
 int add(int a, int b);
}

interface SubInterface{
 int sub(int a, int b);
}

实现类

class Arithmetic implements AddInterface, SubInterface{
 @Override
 public int sub(int a, int b) {
  return a-b;
 }

 @Override
 public int add(int a, int b) {
  return a+b;
 }
}

方式1: JDK自带的动态代理

1、实现方式

  Java在JDK1.3后引入的动态代理机制,使我们可以在运行期动态的创建代理类。使用动态代理实现AOP需要有四个角色:被代理的类,被代理类的接口,织入器,和InvocationHandler,而织入器使用接口反射机制生成一个代理类,然后在这个代理类中织入代码。被代理的类是AOP里所说的目标,InvocationHandler是切面,它包含了Advice和Pointcut。

2、vInvocationHandler接口的实现

class JdkDPQueryHandler implements InvocationHandler{
 private Arithmetic real;
 public JdkDPQueryHandler(Arithmetic real){
  this.real = real;
 }
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  String methodName = method.getName();
  System.out.println(method);
  System.out.println("the method: " + methodName + "开始, 参数: "+Arrays.asList(args));
  Object result = method.invoke(real, args);
  System.out.println("the method: "+methodName+"结束, 结果: " + result);
  return result;
 }
}

3、创建代理类并且调用代理类

public class Main{
 private static int a = 4, b = 2;

 public static Object createJDKProxy(Arithmetic real){
  Object proxyArithmetic = Proxy.newProxyInstance(real.getClass().getClassLoader(),
    real.getClass().getInterfaces(), new JdkDPQueryHandler(real));
  return proxyArithmetic;
 }

 public static void main(String[] args){
  Arithmetic real = new Arithmetic();
  Object proxyArithmetic = createJDKProxy(real);
  ((AddInterface)proxyArithmetic).add(a, b);
  ((SubInterface)proxyArithmetic).sub(a, b);
 }
}

方式2:动态字节码生成(cglib)

1、实现方式

  Enhancer和MethodInterceptor。Enhancer可以用来动态的生成一个类,这个类可以继承指定的一个类,实现指定的一些接口。同时,Enhancer在生成一个类之前需要指定一个Callback,当类方法调用时,方法的执行被分配给这个Callback,MethodInterceptor是一个使用比较多的继承自Callback的接口,它只有一个方法声明。

2、接口InvocationHandler(jdk中)和接口MethodInterceptor(cglib中)对比

public interface MethodInterceptor extends Callback {
 public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,MethodProxy proxy) throws Throwable;
}
public interface InvocationHandler {
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

   从参数构成上,methodInterceptor的输入参数比Invocationhandler多1个,其实前3个参数对象的含义与Invocationhandler的含义是相同的。
  第一个参数表示调用方法来自哪个对象;
  第二个参数表示调用方法的Method对象;
  第三个参数表示此次调用的输入参数列表;
  多出来的参数是MethodProxy 类型的,它应该是cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升。
3、实现1

MethodInterceptor接口的实现

class CglibDPQueryInterceptor implements MethodInterceptor{
 private Arithmetic real;
 public CglibDPQueryInterceptor(Arithmetic real){
  this.real = real;
 }

 @Override
 public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  String methodName = method.getName();
  System.out.println(method);
  System.out.println("the method: " + methodName + "开始, 参数: "+Arrays.asList(args));
  //Object result = method.invoke(real, args);//两种方式都是可以得
  Object result = proxy.invoke(real, args);
  System.out.println("the method: "+methodName+"结束, 结果: " + result);
  return result;
 }
}

创建代理类并调用代理类

public class Main{
 private static int a = 4, b = 2;
 public static Object createCglibProxy(Arithmetic real){
   Enhancer enhancer = new Enhancer();
   enhancer.setCallback(new CglibDPQueryInterceptor(real));
   enhancer.setInterfaces(real.getClass().getInterfaces());
   return enhancer.create();
 }

 public static void main(String[] args){
  Arithmetic real = new Arithmetic();
  Object proxyArithmetic = createCglibProxy(real);
  ((AddInterface)proxyArithmetic).add(a, b);
  ((SubInterface)proxyArithmetic).sub(a, b);
 }
}

注意了,MethodProxy在对执行函数的时候,提供了2个方法

public Object invoke (Object obj, Object[] args) throws Throwable
public Object invokeSuper(Object obj, Object[] args) throws Throwable

  其中,javadoc上说这个invoke()方法可以用于相同类中的其他对象的方法执行,也就是说这个方法中的obj需要传入相同一个类的另一个对象(上述方法中就是传入了Arithmetic类的不同对象),否则会进入无限递归循环(测试之后还真是出现了StackOverflowError)。仔细的想一想就会发现,public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy)中的target是实现的代理类对象,通过target调用add()方法时会触发intercept()方法被调用,如果在intercept()方法中再调用method.invoke(target, args),就相当于add()方法中又调用add()方法,导致无限的递归循环。但是如果执行method.invoke(real, args)则不会,因为real和target是同一个类不同对象,real是真实逻辑主题,target是真实主题real的代理。

  下面一个例子来模拟一下:

interface SolveInterface{
 void solve();
}

class Real implements SolveInterface{
 public void solve(){
  System.out.println("Real Solve!");
 }
}

class Target extends Real{
 private Object obj;

 public void setObject(Object obj){
  this.obj = obj;
 }

 private void invoke(){
  try {
   Method method = SolveInterface.class.getMethod("solve", new Class[]{});
   method.invoke(obj, new Class[]{});
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 public void solve(){
  System.out.println("Target Solve!");
  invoke();
 }
}
public class Main{public static void main(String[] args) throws Exception{
    Target target = new Target();
    target.setObject(new Real());//正确
    //target.setObject(target);//发生循环调用
    target.solve();
  }
}

其实Method的invoke()方法会根据obj的类型去调用对应的solve()方法,也就是多态性。

4、实现2

  MethodInterceptor接口的实现

class CglibDPQueryInterceptor implements MethodInterceptor{

  @Override
  public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    String methodName = method.getName();
    System.out.println(method);
    System.out.println("the method: " + methodName + "开始, 参数: "+Arrays.asList(args));
    // 打印类信息 :target.getClass();省略
    Object result = proxy.invokeSuper(target, args);
    System.out.println("the method: "+methodName+"结束, 结果: " + result);
    return result;
  }
}

创建代理类并调用代理类

public class Main{
  private static int a = 4, b = 2;
public static Object createCglibProxy(){
     Enhancer enhancer = new Enhancer();
     enhancer.setCallback(new CglibDPQueryInterceptor());
     enhancer.setSuperclass(Arithmetic.class);
     return enhancer.create();
  }

  public static void main(String[] args){
    Arithmetic real = new Arithmetic();

    Object proxyArithmetic = createCglibProxy();

    ((AddInterface)proxyArithmetic).add(a, b);
    ((SubInterface)proxyArithmetic).sub(a, b);
  }
}

  注意了,实现2中Enhancer 没有设置接口,因为设置了Superclass了(也就是代理类的父类是Arithmetic),我们的代理类会继承它,而Arithmetic已经实现了我们的接口。为了证明这一点,可以在MethodInterceptor的 intercept方法中打印 target.getClass()的类信息,你会发现cglib的两种方式代理类的父类是不同的。如下:

  实现1:

public class com.test.Arithmetic$$EnhancerByCGLIB$$4fa786eb extends java.lang.Object

  实现2:

public class com.test.Arithmetic$$EnhancerByCGLIB$$4fa786eb extends com.test.Arithmetic

方式3:javassist生成动态代理(代理工厂创建 或者 动态代码创建)  

  Javassist是一个编辑字节码的框架,可以让你很简单地操作字节码。它可以在运行期定义或修改Class。使用Javassist实现AOP的原理是在字节码加载前直接修改需要切入的方法。这比使用Cglib实现AOP更加高效,并且没太多限制,实现原理如下图:

实现1:

接口的实现

class JavassistDPQueryHandler implements MethodHandler{

  @Override
  public Object invoke(Object target, Method method, Method proxy, Object[] args) throws Throwable {
    String methodName = method.getName();
    System.out.println(method);
    System.out.println("the method: " + methodName + "开始, 参数: "+Arrays.asList(args));
    Object result = proxy.invoke(target, args);
    System.out.println("the method: "+methodName+"结束, 结果: " + result);
    return result;
  }
}

创建代理类并调用代理类

public class Main{
  private static int a = 4, b = 2;
public static Object createJavassistProxy() throws Exception{
    ProxyFactory factory = new ProxyFactory();
    factory.setSuperclass(Arithmetic.class);
    factory.setHandler(new JavassistDPQueryHandler());
    return factory.createClass().newInstance();
  }

  public static void main(String[] args) throws Exception{
    Arithmetic real = new Arithmetic();

    Object proxyArithmetic = createJavassistProxy();

    ((AddInterface)proxyArithmetic).add(a, b);
    ((SubInterface)proxyArithmetic).sub(a, b);
  }
}

注意:MethodHandler接口中invoke方法的定义,如下:

public Object invoke(Object target, Method method, Method proxy, Object[] args)

method代表调用方法的Method对象,proxy是代理类产生并代替method的对象,否则用method.invoke(target, args)会产生无限循环调用。

实现2:

  javassist使用动态java代码常见代理过程和前文的方法略有不同。javassist内部可以通过动态java代码,生成字节码。这种方式创建的动态代理可以非常灵活,甚至可以在运行时产生业务逻辑。

//自定义拦截器接口
interface InterceptorHandler { 

  /**
   * 调用动态代理对象的方法将反射本方法,可在本方法实现中添加类似AOP的事前事后操作,只有在本方法体中加入如下代码
   * 被代理的方法才会被执行,返回值将返回给代理最后返回给程序
   * @param obj Object 被代理的对象
   * @param method Method 被代理对象的方法
   * @param args Object[] 被代理对象的方法的参数
   * @return Object 被代理对象的方法执行后的返回值
   * @throws Throwable
   */
  public Object invoke(Object obj, Method method, Object[] args) throws Throwable;
} 

//拦截器的实现
class InterceptorHandlerImpl implements InterceptorHandler{
  @Override
  public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
    String methodName = method.getName();
    System.out.println(method);
    System.out.println("the method: " + methodName + "开始, 参数: "+Arrays.asList(args));
    Object result = method.invoke(obj, args);
    System.out.println("the method: "+methodName+"结束, 结果: " + result);
    return result;
  }
}

class MyProxyImpl {
  /** 动态代理类的类名后缀 */
  private final static String PROXY_CLASS_NAME_SUFFIX = "$MyProxy_";
  /** 拦截器接口 */
  private final static String INTERCEPTOR_HANDLER_INTERFACE = "com.test.InterceptorHandler";
  /** 动态代理类的类名索引,防止类名重复 */
  private static int proxyClassIndex = 1; 

  /**
   * 暴露给用户的动态代理接口,返回某个接口的动态代理对象,注意本代理实现需和com.cuishen.myAop.InterceptorHandler拦截器配合
   * 使用,即用户要使用本动态代理,需先实现com.cuishen.myAop.InterceptorHandler拦截器接口
   * @param interfaceClassName String 要动态代理的接口类名, e.g test.StudentInfoService
   * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl
   * @param interceptorHandlerImplClassName String 用户提供的拦截器接口的实现类的类名
   * @return Object 返回某个接口的动态代理对象
   * @throws InstantiationException
   * @throws IllegalAccessException
   * @throws NotFoundException
   * @throws CannotCompileException
   * @throws ClassNotFoundException
   * @see com.cuishen.myAop.InterceptorHandler
   */
  public static Object newProxyInstance(String interfaceClassName, String classToProxy, String interceptorHandlerImplClassName) throws InstantiationException, IllegalAccessException, NotFoundException, CannotCompileException, ClassNotFoundException {
    Class interfaceClass = Class.forName(interfaceClassName);
    Class interceptorHandlerImplClass = Class.forName(interceptorHandlerImplClassName);
    return dynamicImplementsInterface(classToProxy, interfaceClass, interceptorHandlerImplClass);
  } 

  /**
   * 动态实现要代理的接口
   * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl
   * @param interfaceClass Class 要动态代理的接口类, e.g test.StudentInfoService
   * @param interceptorHandlerImplClass Class 用户提供的拦截器接口的实现类
   * @return Object 返回某个接口的动态代理对象
   * @throws NotFoundException
   * @throws CannotCompileException
   * @throws InstantiationException
   * @throws IllegalAccessException
   */
  private static Object dynamicImplementsInterface(String classToProxy, Class interfaceClass, Class interceptorHandlerImplClass) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException {
    ClassPool cp = ClassPool.getDefault();
    String interfaceName = interfaceClass.getName();
    //动态指定代理类的类名
    String proxyClassName = interfaceName + PROXY_CLASS_NAME_SUFFIX + proxyClassIndex++;
    //要实现的接口的包名+接口名
    String interfaceNamePath = interfaceName; 

    CtClass ctInterface = cp.getCtClass(interfaceNamePath);
    CtClass cc = cp.makeClass(proxyClassName);
    cc.addInterface(ctInterface);
    Method [] methods = interfaceClass.getMethods();
    for(int i = 0; i < methods.length; i++) {
      Method method = methods[i];
      dynamicImplementsMethodsFromInterface(classToProxy, cc, method, interceptorHandlerImplClass, i);
    }
    return (Object)cc.toClass().newInstance();
  } 

  /**
   * 动态实现接口里的方法
   * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl
   * @param implementer CtClass 动态代理类的包装
   * @param methodToImpl Method 动态代理类里面要实现的接口方法的包装
   * @param interceptorClass Class 用户提供的拦截器实现类
   * @param methodIndex int 要实现的方法的索引
   * @throws CannotCompileException
   */
  private static void dynamicImplementsMethodsFromInterface(String classToProxy, CtClass implementer, Method methodToImpl, Class interceptorClass, int methodIndex) throws CannotCompileException {
    String methodCode = generateMethodCode(classToProxy, methodToImpl, interceptorClass, methodIndex);
    CtMethod cm = CtNewMethod.make(methodCode, implementer);
    implementer.addMethod(cm);
  } 

  /**
   * 动态组装方法体,当然代理里面的方法实现并不是简单的方法拷贝,而是反射调用了拦截器里的invoke方法,并将接收到的参数进行传递
   * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl
   * @param methodToImpl Method 动态代理类里面要实现的接口方法的包装
   * @param interceptorClass Class 用户提供的拦截器实现类
   * @param methodIndex int 要实现的方法的索引
   * @return String 动态组装的方法的字符串
   */
  private static String generateMethodCode(String classToProxy, Method methodToImpl, Class interceptorClass, int methodIndex) {
    String methodName = methodToImpl.getName();
    String methodReturnType = methodToImpl.getReturnType().getName();
    Class[] parameters = methodToImpl.getParameterTypes();
    Class[] exceptionTypes = methodToImpl.getExceptionTypes();
    StringBuffer exceptionBuffer = new StringBuffer();
    //组装方法的Exception声明
    if(exceptionTypes.length > 0) exceptionBuffer.append(" throws ");
    for(int i = 0; i < exceptionTypes.length; i++) {
      if(i != exceptionTypes.length - 1) exceptionBuffer.append(exceptionTypes[i].getName()).append(",");
      else exceptionBuffer.append(exceptionTypes[i].getName());
    }
    StringBuffer parameterBuffer = new StringBuffer();
    //组装方法的参数列表
    for(int i = 0; i < parameters.length; i++) {
      Class parameter = parameters[i];
      String parameterType = parameter.getName();
      //动态指定方法参数的变量名
      String refName = "a" + i;
      if(i != parameters.length - 1) parameterBuffer.append(parameterType).append(" " + refName).append(",");
      else parameterBuffer.append(parameterType).append(" " + refName);
    }
    StringBuffer methodDeclare = new StringBuffer();
    //方法声明,由于是实现接口的方法,所以是public
    methodDeclare.append("public ").append(methodReturnType).append(" ").append(methodName).append("(").append(parameterBuffer).append(")").append(exceptionBuffer).append(" {\n");
    String interceptorImplName = interceptorClass.getName();
    //方法体
    methodDeclare.append(INTERCEPTOR_HANDLER_INTERFACE).append(" interceptor = new ").append(interceptorImplName).append("();\n");
    //反射调用用户的拦截器接口
    methodDeclare.append("Object returnObj = interceptor.invoke(Class.forName(\"" + classToProxy + "\").newInstance(), Class.forName(\"" + classToProxy + "\").getMethods()[" + methodIndex + "], ");
    //传递方法里的参数
    if(parameters.length > 0) methodDeclare.append("new Object[]{");
    for(int i = 0; i < parameters.length; i++) {
      //($w) converts from a primitive type to the corresponding wrapper type: e.g.
      //Integer i = ($w)5;
      if(i != parameters.length - 1) methodDeclare.append("($w)a" + i + ",");
      else methodDeclare.append("($w)a" + i);
    }
    if(parameters.length > 0) methodDeclare.append("});\n");
    else methodDeclare.append("null);\n");
    //对调用拦截器的返回值进行包装
    if(methodToImpl.getReturnType().isPrimitive()) {
      if(methodToImpl.getReturnType().equals(Boolean.TYPE)) methodDeclare.append("return ((Boolean)returnObj).booleanValue();\n");
      else if(methodToImpl.getReturnType().equals(Integer.TYPE)) methodDeclare.append("return ((Integer)returnObj).intValue();\n");
      else if(methodToImpl.getReturnType().equals(Long.TYPE)) methodDeclare.append("return ((Long)returnObj).longValue();\n");
      else if(methodToImpl.getReturnType().equals(Float.TYPE)) methodDeclare.append("return ((Float)returnObj).floatValue();\n");
      else if(methodToImpl.getReturnType().equals(Double.TYPE)) methodDeclare.append("return ((Double)returnObj).doubleValue();\n");
      else if(methodToImpl.getReturnType().equals(Character.TYPE)) methodDeclare.append("return ((Character)returnObj).charValue();\n");
      else if(methodToImpl.getReturnType().equals(Byte.TYPE)) methodDeclare.append("return ((Byte)returnObj).byteValue();\n");
      else if(methodToImpl.getReturnType().equals(Short.TYPE)) methodDeclare.append("return ((Short)returnObj).shortValue();\n");
    } else {
      methodDeclare.append("return (" + methodReturnType + ")returnObj;\n");
    }
    methodDeclare.append("}");
    System.out.println(methodDeclare.toString());
    return methodDeclare.toString();
  } 

} 

public class Main{
  public static void main(String[] args) throws Exception{
     //分别对应 代理类要实现的接口类名, 需要代理类的类名, 用户自定义拦截器实现类的类名
    Object proxyArithmetic = MyProxyImpl.newProxyInstance("com.test.ArithmeticInterface", "com.test.Arithmetic",
                                    "com.test.InterceptorHandlerImpl");
    ((ArithmeticInterface)proxyArithmetic).add(a, b);
    ((ArithmeticInterface)proxyArithmetic).sub(a, b);
  }
}

打印一下动态实现接口的代码如下:

public int add(int a0,int a1) {
com.test.InterceptorHandler interceptor = new com.test.InterceptorHandlerImpl();
Object returnObj = interceptor.invoke(Class.forName("com.test.Arithmetic").newInstance(), Class.forName("com.test.Arithmetic").getMethods()[0], new Object[]{($w)a0,($w)a1});
return ((Integer)returnObj).intValue();
}
public int sub(int a0,int a1) {
com.test.InterceptorHandler interceptor = new com.test.InterceptorHandlerImpl();
Object returnObj = interceptor.invoke(Class.forName("com.test.Arithmetic").newInstance(), Class.forName("com.test.Arithmetic").getMethods()[1], new Object[]{($w)a0,($w)a1});
return ((Integer)returnObj).intValue();
}

以上就是关于java中动态代理实现机制的详细介绍,希望对大家的学习有所帮助。

(0)

相关推荐

  • 代理模式之Java动态代理实现方法

    今天一个偶然的机会我突然想看看JDK的动态代理,因为以前也知道一点,而且只是简单的想测试一下使用,使用很快里就写好了这么几个接口和类:接口类:UserService.java 复制代码 代码如下: package com.yixi.proxy;public interface UserService {    public int save() ;    public void update(int id);} 实现类:UserServiceImpl.java 复制代码 代码如下: packag

  • 详解Java动态代理的实现机制

    一.概述 代理是一种设计模式,其目的是为其他对象提供一个代理以控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息以及进行消息被委托类执行后的后续处理.为了保持行为的一致性,代理类和委托类通常会实现相同的接口. 按照代理的创建时期,代理类可分为两种: 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,也就是说在程序运行前代理类的.class文件就已经存在. 动态代理:在程序运行时运用反射机制动态创建生成. 下面在将动态代理的实现机制之前先简单介绍一下静态代理. 二

  • java实现动态代理方法浅析

    一些Java项目中在mybatis与spring整合中有MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 有鉴于此,本文浅析了java的动态代理. 本文使用动态代理模拟处理事务的拦截器. 接口: public interface UserService { public void addUser(); public void removeUser(); public void searchUser(); } 实现类: public class

  • 基于接口实现java动态代理示例

    Subject.java 复制代码 代码如下: package _20140416_; import java.util.List; public interface Subject {   public String say(String name,int age);   public List<Person> getAllList(String name);} RealSubject.java 复制代码 代码如下: package _20140416_; import java.util.

  • 十分钟理解Java中的动态代理

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,"委托者"对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就

  • java动态代理详解

    代理都知道吧,你去买东西就有很多的代理商,他们就是卖原厂的东西.比如,你天天要买肉,猪是农民伯伯养的,但你是从屠夫手上买到肉的,这个屠夫就可以当成是代理.那为什么要代理呢,代理有什么用呢,当然是有事给他做了,对于屠夫这个代理就好理解了,因为你自己不可能去宰猪吧,所以代理就是去买活猪,然后宰掉再卖给你,当然屠夫有可能给肉注点水,关键看他坏不坏,所以屠夫的整个流程就是: 这个流程用代码怎么实现呢:我们应该要用三个类You.Butcher.Farmer分别指你.屠夫.农民伯伯.其中农民伯伯又提供一个买

  • java代理模式与动态代理模式详解

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 生活中的例子:过年加班比较忙,没空去买火车票,这时可以打个电话到附近的票务中心,叫他们帮你买张回家的火车票,当然这会附加额外的劳务费.但要清楚票务中心自己并不卖票,只有火车站才真正卖票,票务中心卖给你的票其实是通过火车站实现的.这点很重要!

  • Java动态代理实现_动力节点Java学院整理

    动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的方法都被固定,这种代理被称之为静态代理(Static Proxy).那么有没有一种机制能够让系统在运行时动态创建代理类?答案就是本文将要介绍的动态代理(Dynamic Proxy).动态代理是一种较为高级的代理模式,它在事务管理.AOP(Aspect-Ori

  • Java动态代理的应用详解

    动态代理其实就是java.lang.reflect.Proxy类动态的根据您指定的所有接口生成一个class byte,该class会继承Proxy类,并实现所有你指定的接口(您在参数中传入的接口数组):然后再利用您指定的classloader将 class byte加载进系统,最后生成这样一个类的对象,并初始化该对象的一些值,如invocationHandler,以即所有的接口对应的Method成员. 初始化之后将对象返回给调用的客户端.这样客户端拿到的就是一个实现你所有的接口的Proxy对象

  • 详解java中动态代理实现机制

    代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. JAVA各种动态代理实现的比较 接口 interface AddInterface{ int add(int a, int b); } interface SubInterfa

  • 详解Java JDK动态代理

    今天来看看Java的另一种代理方式--JDK动态代理 我们之前所介绍的代理方式叫静态代理,也就是静态的生成代理对象,而动态代理则是在运行时创建代理对象.动态代理有更强大的拦截请求功能,因为可以获得类的运行时信息,可以根据运行时信息来获得更为强大的执(骚)行(操)力(作). 我们还是以上一个例子为例,这里的IStars接口和Stars类都不需要修改,只需要修改代理类. 创建JDK动态代理需要先实现InvocationHandler接口,并重写其中的invoke方法,具体步骤如下: 1. 创建一个类

  • 详解java JDK 动态代理类分析(java.lang.reflect.Proxy)

    详解java JDK 动态代理类分析(java.lang.reflect.Proxy) /** * JDK 动态代理类分析(java.lang.reflect.Proxy使用) * * @author 张明学 * */ public class ProxyStudy { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { // 动态代理类:通用指定类加载器,和接

  • 详解Java Cglib动态代理

    今天来介绍另一种更为强大的代理--Cglib动态代理. 什么是Cglib动态代理? 我们先回顾一下上一篇的jdk动态代理,jdk动态代理是通过接口来在运行时动态创建委托类的代理对象,但是跟静态代理一样有一个缺点,就是必须和委托类实现相同的接口,当接口数量增加时,便需要增加代理类的数量才能满足需求,而且如果委托类是别人写的,而且没有实现任何接口,那么jdk动态代理就有些力不从心了. 这时候Cglib动态代理就脱颖而出了,Cglib并不依赖接口,可以直接生成委托类的代理对象,而且可以代理委托类的任意

  • 详解java中各类锁的机制

    目录 前言 1. 乐观锁与悲观锁 2. 公平锁与非公平锁 3. 可重入锁 4. 读写锁(共享锁与独占锁) 6. 自旋锁 7. 无锁 / 偏向锁 / 轻量级锁 / 重量级锁 前言 总结java常见的锁 区分各个锁机制以及如何使用 使用方法 锁名 考察线程是否要锁住同步资源 乐观锁和悲观锁 锁住同步资源后,要不要阻塞 不阻塞可以使用自旋锁 一个线程多个流程获取同一把锁 可重入锁 多个线程公用一把锁 读写锁(写的共享锁) 多个线程竞争要不要排队 公平锁与非公平锁 1. 乐观锁与悲观锁 悲观锁:不能同时

  • 详解Java Proxy动态代理机制

    一.Jvm加载对象 在说Java动态代理之前,还是要说一下Jvm加载对象的过程,这个依旧是理解动态代理的基础性原理: Java类即源代码程序.java类型文件,经过编译器编译之后就被转换成字节代码.class类型文件,类加载器负责读取字节代码,并转换成java.lang.Class对象,描述类在元数据空间的数据结构,类被实例化时,堆中存储实例化的对象信息,并且通过对象类型数据的指针找到类. 过程描述:源码->.java文件->.class文件->Class对象->实例对象 所以通过

  • 详解Java中的反射机制和动态代理

    一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制.通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以,这是一种动态获取类的信息以及动态调用对象方法的能力. 想要使用反射机制,就必须要先获取到该类

  • 一文详解Java中的类加载机制

    目录 一.前言 二.类加载的时机 2.1 类加载过程 2.2 什么时候类初始化 2.3 被动引用不会初始化 三.类加载的过程 3.1 加载 3.2 验证 3.3 准备 3.4 解析 3.5 初始化 四.父类和子类初始化过程中的执行顺序 五.类加载器 5.1 类与类加载器 5.2 双亲委派模型 5.3 破坏双亲委派模型 六.Java模块化系统 一.前言 Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最 终形成可以被虚拟机直接使用的Java类型,这个过程

  • 详解java中反射机制(含数组参数)

    详解java中反射机制(含数组参数) java的反射是我一直非常喜欢的地方,因为有了这个,可以让程序的灵活性大大的增加,同时通用性也提高了很多.反射原理什么的,我就不想做过大介绍了,网上一搜,就一大把.(下面我是只附录介绍下) Reflection 是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等).superclass(例如O

  • java 中动态代理机制的实例讲解

    java 中动态代理机制的实例讲解 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾. 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)

随机推荐