[Java] 模拟Jdk 以及 CGLib 代理原理

简介: [Java] 模拟Jdk 以及 CGLib 代理原理


JDK

Jdk代理的最简单模拟, 由前文可知 JDK动态代理需要实现接口,所以基于此,进行最简单的模拟。

package com.example.proxy;
public class Jdk {
    interface Foo {
        void foo();
    }
    static class Target implements Foo {
        @Override
        public void foo() {
            System.out.println("foo");
        }
    }
    // 代理类
    static class $Proxy0 implements Foo {
        @Override
        public void foo() {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            new Target().foo();
        }
    }
    public static void main(String[] args) {
        Foo f = new $Proxy0();
        f.foo();
    }
}

虽然简单实现了代理,但是目前增强是固定的,但是在实际应用中,使用到代理类,方法是不可能固定的,所以接下来进行优化一下。使用抽象类+模版方法设置代理的执行逻辑。

package com.example.proxy;
public class Jdk {
    interface Foo {
        void foo();
    }
    static abstract class InvokeHandler {
        abstract Object invoke();
    }
    // 代理类
    static class $Proxy0 implements Foo {
        private final InvokeHandler invokeHandler;
        $Proxy0(InvokeHandler invokeHandler) {
            this.invokeHandler = invokeHandler;
        }
        @Override
        public void foo() {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            invokeHandler.invoke();
        }
    }
    public static void main(String[] args) {
        Foo f = new $Proxy0(new InvokeHandler() {
            @Override
            Object invoke() {
                System.out.println(">>>>>>>> foo");
                return null;
            }
        });
        f.foo();
    }
}

至此,方法就是可以不再固定。但是很显然,代理的对象不可能永远只有一个方法,所以想办法动态设置。

package com.example.proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Jdk {
    interface Foo {
        void foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
        void bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
    }
    static abstract class InvokeHandler {
        abstract Object invoke(Method method, Object[] params) throws InvocationTargetException, IllegalAccessException;
    }
    // 代理类
    static class $Proxy0 implements Foo {
        private final InvokeHandler invokeHandler;
        $Proxy0(InvokeHandler invokeHandler) {
            this.invokeHandler = invokeHandler;
        }
        @Override
        public void foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            invokeHandler.invoke(Foo.class.getMethod("foo"), new Object[0]);
        }
        @Override
        public void bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            invokeHandler.invoke(Foo.class.getMethod("bar"), new Object[0]);
        }
    }
    static class Target implements Foo {
        @Override
        public void foo() {
            System.out.println("target foo");
        }
        @Override
        public void bar() {
            System.out.println("target bar");
        }
    }
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Foo f = new $Proxy0(new InvokeHandler() {
            @Override
            Object invoke(Method method, Object[] params) throws InvocationTargetException, IllegalAccessException {
                // 传入代理对象
                method.invoke(new Target(), params);
                return null;
            }
        });
        f.foo();
        f.bar();
    }
}

/**

运行结果

before

target foo

before

target bar

**/

到这里,可以发现,多方法的代理对象也可以正常执行。但是如果执行方法有值返回呢,这个也简单,小修改一波。

package com.example.proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Jdk {
    interface Foo {
        Object foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
        Object bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
    }
    static abstract class InvokeHandler {
        abstract Object invoke(Method method, Object[] params) throws InvocationTargetException, IllegalAccessException;
    }
    // 代理类
    static class $Proxy0 implements Foo {
        private final InvokeHandler invokeHandler;
        $Proxy0(InvokeHandler invokeHandler) {
            this.invokeHandler = invokeHandler;
        }
        @Override
        public Object foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            return invokeHandler.invoke(Foo.class.getMethod("foo"), new Object[0]);
        }
        @Override
        public Object bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            return invokeHandler.invoke(Foo.class.getMethod("bar"), new Object[0]);
        }
    }
    static class Target implements Foo {
        @Override
        public Integer foo() {
            System.out.println("target foo");
            return 1;
        }
        @Override
        public String  bar() {
            System.out.println("target bar");
            return "hello";
        }
    }
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Foo f = new $Proxy0(new InvokeHandler() {
            @Override
            Object invoke(Method method, Object[] params) throws InvocationTargetException, IllegalAccessException {
                // 传入代理对象
                return method.invoke(new Target(), params);
            }
        });
        System.out.println(f.foo());
        System.out.println(f.bar());
    }
}
/**
运行结果
before
target foo
1
before
target bar
hello
**/

在源码实现中,方法还可以被缓存复用,不需要每次都重新创建。

package com.example.proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class Jdk {
    interface Foo {
        Object foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
        Object bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
    }
    static abstract class InvokeHandler {
        abstract Object invoke(Method method, Object[] params) throws InvocationTargetException, IllegalAccessException;
    }
    // 代理类
    static class $Proxy0 implements Foo {
        private final InvokeHandler invokeHandler;
        private final Map<String, Method> cache = new HashMap<>();
        $Proxy0(InvokeHandler invokeHandler) {
            this.invokeHandler = invokeHandler;
        }
        @Override
        public Object foo() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            Method foo = cache.getOrDefault("foo", null);
            if(foo == null) {
                foo = Foo.class.getMethod("foo");
                System.out.println(">>>>>> 新创建方法");
                cache.put("foo", foo);
            }
            return invokeHandler.invoke(foo, new Object[0]);
        }
        @Override
        public Object bar() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            // 1. 功能增强
            System.out.println("before");
            // 2. 调用目标
            Method bar = cache.getOrDefault("bar", null);
            if(bar == null) {
                bar = Foo.class.getMethod("foo");
                System.out.println(">>>>>> 新创建方法");
                cache.put("bar", bar);
            }
            return invokeHandler.invoke(bar, new Object[0]);
        }
    }
    static class Target implements Foo {
        @Override
        public Integer foo() {
            System.out.println("target foo");
            return 1;
        }
        @Override
        public String  bar() {
            System.out.println("target bar");
            return "hello";
        }
    }
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Foo f = new $Proxy0(new InvokeHandler() {
            @Override
            Object invoke(Method method, Object[] params) throws InvocationTargetException, IllegalAccessException {
                // 传入代理对象
                return method.invoke(new Target(), params);
            }
        });
        System.out.println(f.foo());
        System.out.println(f.bar());
        System.out.println(f.foo());
        System.out.println(f.bar());
    }
}
/**
before
>>>>>> 新创建方法
target foo
1
before
>>>>>> 新创建方法
target foo
1
before
target foo
1
before
target foo
1
**/

到此,代理方法只会被寻找一次。

JDK 动态代理生成的代理类是以字节码的形式存在的,并不存在所谓的 .java 文件,但也不是说就没办法看到生成的代理类信息了。不过可

以使用 arthas反编译,看到字节码。

arthas 反编译jdk代理对象

比如:

package com.example.proxy;
import java.io.IOException;
import java.lang.reflect.Proxy;
public class Jdk1 {
    interface Foo {
        void foo();
    }
    static final class Target implements Foo {
        @Override
        public void foo() {
            System.out.println("target foo");
        }
    }
    public static void main(String[] args) throws IOException {
        // 原始对象
        Target target = new Target();
        // 用来加载在运行期间动态生成的字节码
        ClassLoader classLoader = Jdk1.class.getClassLoader();
        Foo proxy = (Foo) Proxy.newProxyInstance(classLoader, new Class[]{Foo.class}, (p, method, params) -> {
            System.out.println("before...");
            // 目标.方法(参数) --> 方法.invoke(目标, 参数)
            Object result = method.invoke(target, params);
            System.out.println("after...");
            // 也返回目标方法执行的结果
            return result;
        });
        // 打印代理类的全限定类名
        System.out.println(proxy.getClass());
        proxy.foo();
        // 只要不在控制台上输入并回车,程序就不会终端
        System.in.read();
    }
}

打印的结果是:

class com.example.proxy.$Proxy0
before...
target foo
after...

arthas 反编译的结果是:

[arthas@60054]$ jad com.example.proxy.$Proxy0

ClassLoader:

±jdk.internal.loader.ClassLoadersA p p C l a s s L o a d e r @ 251 a 69 d 7 + − j d k . i n t e r n a l . l o a d e r . C l a s s L o a d e r s AppClassLoader@251a69d7 +-jdk.internal.loader.ClassLoadersAppClassLoader@251a69d7+jdk.internal.loader.ClassLoadersPlatformClassLoader@17747fbe

Location:

/*
 * Decompiled with CFR.
 *
 * Could not load the following classes:
 *  com.example.proxy.Jdk1$Foo
 */
package com.example.proxy;
import com.example.proxy.Jdk1;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
final class $Proxy0
extends Proxy
implements Jdk1.Foo {
    private static final Method m0;
    private static final Method m1;
    private static final Method m2;
    private static final Method m3;
    private static MethodHandles.Lookup proxyClassLookup(MethodHandles.Lookup lookup) throws IllegalAccessException {
        if (lookup.lookupClass() == Proxy.class && lookup.hasFullPrivilegeAccess()) {
            return MethodHandles.lookup();
        }
        throw new IllegalAccessException(lookup.toString());
    }
    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }
    static {
        try {
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("com.example.proxy.Jdk1$Foo").getMethod("foo", new Class[0]);
            return;
        }
        catch (NoSuchMethodException noSuchMethodException) {
            throw new NoSuchMethodError(noSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException classNotFoundException) {
            throw new NoClassDefFoundError(classNotFoundException.getMessage());
        }
    }
    public final void foo() {
        try {
            this.h.invoke(this, m3, null);
            return;
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
    public final boolean equals(Object object) {
        try {
            return (Boolean)this.h.invoke(this, m1, new Object[]{object});
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
    public final String toString() {
        try {
            return (String)this.h.invoke(this, m2, null);
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
    public final int hashCode() {
        try {
            return (Integer)this.h.invoke(this, m0, null);
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
}

CGlib

cglib 代理类继承目标对象。

public class Target {
    public void save() {
        System.out.println("0");
    }
    public void save(int i) {
        System.out.println(i);
    }
    public void save(long l) {
        System.out.println(l);
    }
}
//- cglib 代理模拟
public class Proxy extends Target{
    private  MethodInterceptor methodInterceptor;
    public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
        this.methodInterceptor = methodInterceptor;
    }
    private static final Method save0;
    private static final Method save1;
    private static final Method save2;
    static {
        try {
            save0 = Target.class.getMethod("save");
            save1 = Target.class.getMethod("save", int.class);
            save2 = Target.class.getMethod("save", long.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void save()  {
        try {
            methodInterceptor.intercept(this, save0, new Object[0], null);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void save(int i) {
        try {
            methodInterceptor.intercept(this, save1, new Object[]{i}, null);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void save(long l) {
        try {
            methodInterceptor.intercept(this, save2, new Object[]{l}, null);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}
//- 测试类
public class ProxyTest {
    public static void main(String[] args) {
        Target target = new Target();
        Proxy proxy = new Proxy();
        proxy.setMethodInterceptor((obj, method, args1, proxy1) -> {
            System.out.println("before----");
            return method.invoke(target, args1);
        });
        proxy.save();
        proxy.save(1);
        proxy.save(2L);
    }
}

methodProxy 不经过反射调用方法的原理

在在上述 Proxy 类中,重写了父类中的方法,并在重写的方法中调用了 intercept() 方法,重写的这些方法相当于是带增强功能的方法。

在 JDK 的动态代理中,使用反射对方法进行调用,而在 CGLib 动态代理中,可以使用 intercept() 方法中 MethodProxy 类型的参数实现不经过反射来调用方法。

接收的 MethodProxy 类型的参数可以像 Method 类型的参数一样,在静态代码块中被实例化。

public class Proxy extends Target{
    private  MethodInterceptor methodInterceptor;
    public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
        this.methodInterceptor = methodInterceptor;
    }
    static Method save0;
    static Method save1;
    static Method save2;
    static MethodProxy save0Proxy;
    static MethodProxy save1Proxy;
    static MethodProxy save2Proxy;
    static {
        try {
            save0 = Target.class.getMethod("save");
            save1 = Target.class.getMethod("save", int.class);
            save2 = Target.class.getMethod("save", long.class);
            save0Proxy = MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
            save1Proxy = MethodProxy.create(Target.class, Proxy.class, "(I)V", "save", "saveSuper");
            save2Proxy = MethodProxy.create(Target.class, Proxy.class, "(J)V", "save", "saveSuper");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }
    // >>>>>>>>>>>>>>>>>>>>>>>> 带原始功能的方法
    public void saveSuper() {
        super.save();
    }
    public void saveSuper(int i) {
        super.save(i);
    }
    public void saveSuper(long i) {
        super.save(i);
    }
    // >>>>>>>>>>>>>>>>>>>>>>>> 带增强功能的方法
    @Override
    public void save() {
        try {
            methodInterceptor.intercept(this, save0, new Object[0], save0Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
    @Override
    public void save(int i) {
        try {
            methodInterceptor.intercept(this, save1, new Object[]{i}, save1Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
    @Override
    public void save(long i) {
        try {
            methodInterceptor.intercept(this, save2, new Object[]{i}, save2Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}
//- 测试类
public class ProxyTest {
    public static void main(String[] args) {
        Target target = new Target();
        Proxy proxy = new Proxy();
        proxy.setMethodInterceptor((obj, method, args1, methodProxy) -> {
            System.out.println("before----");
//            return method.invoke(target, args1);
//            return methodProxy.invoke(target, args1);  // 内部无反射调用 结合目标对象使用
            return methodProxy.invokeSuper(obj, args1); // 内部无反射调用, 结合代理对象使用
        });
        proxy.save();
        proxy.save(1);
        proxy.save(2L);
    }
}

MethodProxy原理

其内部是通过一个 FastClass+ 方法签名实现

模拟 结合目标对象使用

Target target = new Target();
Target proxy = (Target) Enhancer.create(Target.class, (MethodInterceptor) (obj, method, args, methodProxy) -> {
   System.out.println("before...");
   // 内部没使用反射,需要目标(spring 的选择)
   Object result = methodProxy.invoke(target, args);
   System.out.println("after...");
   return result;
});
package com.example.proxy;
import org.springframework.cglib.core.Signature;
public class TargetFastClass {
   static Signature s0 = new Signature("save", "()V");
   static Signature s1 = new Signature("save", "(I)V");
   static Signature s2 = new Signature("save", "(J)V");
   /**
    * <p>获取目标方法的编号</p>
    * <p>
    * Target 目标类中的方法:
    * save()             0
    * save(int)          1
    * save(long)         2
    * </p>
    *
    * @param signature 包含方法名称、参数返回值
    * @return 方法编号
    */
   public int getIndex(Signature signature) {
       if (s0.equals(signature)) {
           return 0;
       }
       if (s1.equals(signature)) {
           return 1;
       }
       if (s2.equals(signature)) {
           return 2;
       }
       return -1;
   }
   /**
    * 根据 getIndex() 方法返回的方法编号正常调用目标对象方法
    *
    * @param index       方法编号
    * @param target       目标对象
    * @param args 调用目标对象方法需要的参数
    * @return 方法返回结果
    */
   public Object invoke(int index, Object target, Object[] args) {
       if (index == 0) {
           ((Target) target).save();
           return null;
       }
       if (index == 1) {
           ((Target) target).save((int) args[0]);
           return null;
       }
       if (index == 2) {
           ((Target) target).save((long) args[0]);
           return null;
       }
       throw new RuntimeException("无此方法");
   }
   public static void main(String[] args) {
       TargetFastClass fastClass = new TargetFastClass();
       int index = fastClass.getIndex(new Signature("save", "()V"));
       fastClass.invoke(index, new Target(), new Object[0]);
       index = fastClass.getIndex(new Signature("save", "(J)V"));
       fastClass.invoke(index, new Target(), new Object[]{2L});
   }
}

模拟结合 代理对象使用

Target proxy = (Target) Enhancer.create(Target.class, (MethodInterceptor) (obj, method, args, methodProxy) -> {
    System.out.println("before...");
    // 内部没使用反射,需要代理
    Object result = methodProxy.invokeSuper(obj, args);
    System.out.println("after...");
    return result;
});
package com.example.proxy;
import org.springframework.cglib.core.Signature;
public class ProxyFastClass {
    static Signature s0 = new Signature("saveSuper", "()V");
    static Signature s1 = new Signature("saveSuper", "(I)V");
    static Signature s2 = new Signature("saveSuper", "(J)V");
    /**
     * <p>获取代理方法的编号</p>
     * <p>
     * Proxy 代理类中的方法:
     * saveSuper()             0
     * saveSuper(int)          1
     * saveSuper(long)         2
     * </p>
     *
     * @param signature 包含方法名称、参数返回值
     * @return 方法编号
     */
    public int getIndex(Signature signature) {
        if (s0.equals(signature)) {
            return 0;
        }
        if (s1.equals(signature)) {
            return 1;
        }
        if (s2.equals(signature)) {
            return 2;
        }
        return -1;
    }
    /**
     * 根据 getIndex() 方法返回的方法编号正常调用代理对象中带原始功能的方法
     *
     * @param index 方法编号
     * @param proxy 代理对象
     * @param args  调用方法需要的参数
     * @return 方法返回结果
     */
    public Object invoke(int index, Object proxy, Object[] args) {
        if (index == 0) {
            ((Proxy) proxy).saveSuper();
            return null;
        }
        if (index == 1) {
            ((Proxy) proxy).saveSuper((int) args[0]);
            return null;
        }
        if (index == 2) {
            ((Proxy) proxy).saveSuper((long) args[0]);
            return null;
        }
        throw new RuntimeException("无此方法");
    }
    public static void main(String[] args) {
        ProxyFastClass fastClass = new ProxyFastClass();
        int index = fastClass.getIndex(new Signature("saveSuper", "()V"));
        fastClass.invoke(index, new Proxy(), new Object[0]);
        int index1 = fastClass.getIndex(new Signature("saveSuper", "(J)V"));
        fastClass.invoke(index1, new Proxy(), new Object[]{2L});
    }
}


相关文章
|
1天前
|
安全 Java 编译器
JDK 10中的局部变量类型推断:Java编程的简化与革新
JDK 10引入的局部变量类型推断通过`var`关键字简化了代码编写,提高了可读性。编译器根据初始化表达式自动推断变量类型,减少了冗长的类型声明。虽然带来了诸多优点,但也有一些限制,如只能用于局部变量声明,并需立即初始化。这一特性使Java更接近动态类型语言,增强了灵活性和易用性。
78 53
|
1天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
1天前
|
Java
Java之CountDownLatch原理浅析
本文介绍了Java并发工具类`CountDownLatch`的使用方法、原理及其与`Thread.join()`的区别。`CountDownLatch`通过构造函数接收一个整数参数作为计数器,调用`countDown`方法减少计数,`await`方法会阻塞当前线程,直到计数为零。文章还详细解析了其内部机制,包括初始化、`countDown`和`await`方法的工作原理,并给出了一个游戏加载场景的示例代码。
Java之CountDownLatch原理浅析
|
3天前
|
Java 索引 容器
Java ArrayList扩容的原理
Java 的 `ArrayList` 是基于数组实现的动态集合。初始时,`ArrayList` 底层创建一个空数组 `elementData`,并设置 `size` 为 0。当首次添加元素时,会调用 `grow` 方法将数组扩容至默认容量 10。之后每次添加元素时,如果当前数组已满,则会再次调用 `grow` 方法进行扩容。扩容规则为:首次扩容至 10,后续扩容至原数组长度的 1.5 倍或根据实际需求扩容。例如,当需要一次性添加 100 个元素时,会直接扩容至 110 而不是 15。
Java ArrayList扩容的原理
|
9天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
24 2
|
9天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
23 1
|
Java 数据库连接
Java之jdk和CGLib实现动态代理
Java之jdk和CGLib实现动态代理
130 0
|
10天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
1天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
1天前
|
安全 Java 编译器
Java多线程编程的陷阱与最佳实践####
【10月更文挑战第29天】 本文深入探讨了Java多线程编程中的常见陷阱,如竞态条件、死锁、内存一致性错误等,并通过实例分析揭示了这些陷阱的成因。同时,文章也分享了一系列最佳实践,包括使用volatile关键字、原子类、线程安全集合以及并发框架(如java.util.concurrent包下的工具类),帮助开发者有效避免多线程编程中的问题,提升应用的稳定性和性能。 ####
15 1