详解java中动态代理实现机制_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中动态代理实现机制的详细介绍,希望对大家的学习有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
动态代理
java动态代理机制详解、java动态代理详解、java动态代理机制、java的动态代理机制、反射机制的动态代理,以便于您获取更多的相关知识。

时间: 2024-10-18 09:22:11

详解java中动态代理实现机制_java的相关文章

java中动态代理实现机制

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

详解Java中对象序列化与反序列化_java

        序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等.在网络传输过程中,可以是字节或是XML等格式.而字节的或XML编码格式可以还原完全相等的对象.这个相反的过程又称为反序列化.Java对象的序列化与反序列化 在Java中,我们可以通过多种方式来创建对象,并且只要对象没有被回收我们都可以复用该对象.但是,我们创建出来的这些Java对象都是存在于JVM的堆内存中的.只有JVM处于运行状态

图文详解Java中class的初始化顺序_java

class的装载 在讲class的初始化之前,我们来讲解下class的装载顺序. 以下摘自<Thinking in Java 4> 由于Java 中的一切东西都是对象,所以许多活动 变得更加简单,这个问题便是其中的一例.正如下一章会讲到的那样,每个对象的代码都存在于独立的文件中.除非真的需要代码,否则那个文件是不会载入的.通常,我们可认为除非那个类的一个对象构造完毕,否则代码不会真的载入.由于static 方法存在一些细微的歧义,所以也能认为"类代码在首次使用的时候载入".

详解Java中Iterator迭代器的用法_java

迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为"轻量级"对象,因为创建它的代价小. Java中的Iterator功能比较简单,并且只能单向移动: (1) 使用方法iterator()要求容器返回一个Iterator.第一次调用Iterator的next()方法时,它返回序列的第一个元素.注意:iterator()方法是java.lang.Iterable接口,被Collection继承

详解AngularJS中的依赖注入机制

  这篇文章主要介绍了详解AngularJS中的依赖注入机制,对JavaScript各组件的使用起到非常重要的作用,需要的朋友可以参考下 依赖注入是一个在组件中给出的替代了硬的组件内的编码它们的依赖关系的软件设计模式.这减轻一个组成部分,从定位的依赖,依赖配置.这有助于使组件可重用,维护和测试. AngularJS提供了一个至高无上的依赖注入机制.它提供了一个可注入彼此依赖下列核心组件. 值 工厂 服务 提供者 常值 值 值是简单的JavaScript对象,它是用来将值传递过程中的配置相位控制器

详解Java中的正则表达式

详解Java中的正则表达式,并列出常用的正则表达式语法和一些常用的场景. 判断一个字符串是否是由数字组成: 当不使用正则表达式的时候的实现代码: public class RegexDemo01 { public static void main(String[] args) { String s = "23432324"; char c[] = s.toCharArray();//将字符串转换成字符数组 for (int i = 0; i < c.length; i++) {

详解Java中的指针、引用及对象的clone

对象|详解 Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念.并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象.本文会让你了解什么是影子clone与深度clone,认识它们的区别.优点及缺点.看到这个标题,是不是有点困惑:Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,滥用指针写成的

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

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

根据实例详解Java中的反射机制

概念:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.作用:Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理. 可以说Java的反射机制是Java中所有框架的基础,要对SSH等框架有一个深刻的理解