java中动态代理实现机制

简介:

v前言:

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

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

v接口

复制代码
interface AddInterface{
    int add(int a, int b);
}

interface SubInterface{
    int sub(int a, int b);
}
复制代码

v实现类

复制代码
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;
    }
}
复制代码

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

v实现方式

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

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;
    }
}
复制代码

v创建代理类并且调用代理类

复制代码
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);
    }
}
复制代码

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

v实现方式

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

v接口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直接执行方法效率会有提升。

v实现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()方法,也就是多态性。

v实现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的两种方式代理类的父类是不同的。如下:

  (如果需要打印类信息代码,请参考:http://www.cnblogs.com/hujunzheng/p/5132943.html

  实现1:

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

  实现2:

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

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

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

v实现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)会产生无限循环调用。

v实现2:

  (来自:http://cuishen.iteye.com/blog/421464),代码注释很详细,仔细研究一下就会懂了!

  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();
}









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/5134478.html,如需转载请自行联系原作者
目录
相关文章
|
7月前
|
设计模式 人工智能 安全
AQS:Java 中悲观锁的底层实现机制
AQS(AbstractQueuedSynchronizer)是Java并发包中实现同步组件的基础工具,支持锁(如ReentrantLock、ReadWriteLock)和线程同步工具类(如CountDownLatch、Semaphore)等。Doug Lea设计AQS旨在抽象基础同步操作,简化同步组件构建。 使用AQS需实现`tryAcquire(int arg)`和`tryRelease(int arg)`方法以获取和释放资源,共享模式还需实现`tryAcquireShared(int arg)`和`tryReleaseShared(int arg)`。
400 32
AQS:Java 中悲观锁的底层实现机制
|
7月前
|
人工智能 Java 关系型数据库
Java——SPI机制详解
SPI(Service Provider Interface)是JDK内置的服务提供发现机制,主要用于框架扩展和组件替换。通过在`META-INF/services/`目录下定义接口实现类文件,Java程序可利用`ServiceLoader`动态加载服务实现。SPI核心思想是解耦,允许不同厂商为同一接口提供多种实现,如`java.sql.Driver`的MySQL与PostgreSQL实现。然而,SPI存在缺陷:需遍历所有实现并实例化,可能造成资源浪费;获取实现类方式不够灵活;多线程使用时存在安全问题。尽管如此,SPI仍是Java生态系统中实现插件化和模块化设计的重要工具。
262 0
|
5月前
|
人工智能 前端开发 安全
Java开发不可不知的秘密:类加载器实现机制
类加载器是Java中负责动态加载类到JVM的组件,理解其工作原理对开发复杂应用至关重要。本文详解类加载过程、双亲委派模型及常见类加载器,并介绍自定义类加载器的实现与应用场景。
257 4
|
7月前
|
Java 区块链 网络架构
酷阿鲸森林农场:Java 区块链系统中的 P2P 区块同步与节点自动加入机制
本文介绍了基于 Java 的去中心化区块链电商系统设计与实现,重点探讨了 P2P 网络在酷阿鲸森林农场项目中的应用。通过节点自动发现、区块广播同步及链校验功能,系统实现了无需中心服务器的点对点网络架构。文章详细解析了核心代码逻辑,包括 P2P 服务端监听、客户端广播新区块及节点列表自动获取等环节,并提出了消息签名验证、WebSocket 替代 Socket 等优化方向。该系统不仅适用于农业电商,还可扩展至教育、物流等领域,构建可信数据链条。
|
9月前
|
缓存 Dubbo Java
理解的Java中SPI机制
本文深入解析了JDK提供的Java SPI(Service Provider Interface)机制,这是一种基于接口编程、策略模式与配置文件组合实现的动态加载机制,核心在于解耦。文章通过具体示例介绍了SPI的使用方法,包括定义接口、创建配置文件及加载实现类的过程,并分析了其原理与优缺点。SPI适用于框架扩展或替换场景,如JDBC驱动加载、SLF4J日志实现等,但存在加载效率低和线程安全问题。
432 7
理解的Java中SPI机制
|
7月前
|
人工智能 JavaScript Java
Java反射机制及原理
本文介绍了Java反射机制的基本概念、使用方法及其原理。反射在实际项目中比代理更常用,掌握它可以提升编程能力并理解框架设计原理。文章详细讲解了获取Class对象的四种方式:对象.getClass()、类.class、Class.forName()和类加载器.loadClass(),并分析了Class.forName()与ClassLoader的区别。此外,还探讨了通过Class对象进行实例化、获取方法和字段等操作的具体实现。最后从JVM类加载机制角度解析了Class对象的本质及其与类和实例的关系,帮助读者深入理解Java反射的工作原理。
194 0
|
8月前
|
存储 Java 编译器
Java 中 .length 的使用方法:深入理解 Java 数据结构中的长度获取机制
本文深入解析了 Java 中 `.length` 的使用方法及其在不同数据结构中的应用。对于数组,通过 `.length` 属性获取元素数量;字符串则使用 `.length()` 方法计算字符数;集合类如 `ArrayList` 采用 `.size()` 方法统计元素个数。此外,基本数据类型和包装类不支持长度属性。掌握这些区别,有助于开发者避免常见错误,提升代码质量。
806 1
|
8月前
|
缓存 监控 Java
java动态代理
本文介绍了Java中的动态代理及其优势,通过增强原有方法或拦截调用实现无侵入式代码扩展,如添加日志、缓存等。文章先讲解了静态代理的基本概念和实现方式,随后引出动态代理解决静态代理在多方法、多类场景下的局限性。通过JDK提供的InvocationHandler接口和Proxy类,展示了如何动态生成代理对象。最后,文章还探讨了代理Hook技术,包括寻找Hook点、选择代理方式以及替换原始对象的具体步骤。
233 0
|
9月前
|
缓存 运维 Java
Java静态代码块深度剖析:机制、特性与最佳实践
在Java中,静态代码块(或称静态初始化块)是指类中定义的一个或多个`static { ... }`结构。其主要功能在于初始化类级别的数据,例如静态变量的初始化或执行仅需运行一次的初始化逻辑。
301 4
|
10月前
|
Dubbo Java 应用服务中间件
Java的动态代理
Java动态代理是一种强大的机制,允许在运行时创建接口的代理实例,并拦截方法调用。其核心组件包括`java.lang.reflect.Proxy`和`java.lang.reflect.InvocationHandler`。通过自定义接口、实现接口、编写`InvocationHandler`处理器并生成代理对象,可以灵活地增强方法功能,如日志记录、事务管理等。典型应用场景包括AOP、RPC、延迟加载和Mock测试。与CGLIB相比,JDK动态代理基于接口,性能稍慢但无需第三方库,适用于需要无侵入式增强的场合。
259 2