【编程进阶知识】静态代理、JDK动态代理及Cglib动态代理各自存在的缺点及代码示例

简介: 本文介绍了三种Java代理模式:静态代理、JDK动态代理和Cglib动态代理。静态代理针对特定接口或对象,需手动编码实现;JDK动态代理通过反射机制实现,适用于所有接口;Cglib动态代理则基于字节码技术,无需接口支持,但需引入外部库。每种方法各有优缺点,选择时应根据具体需求考虑。

本文介绍了三种Java代理模式:静态代理、JDK动态代理和Cglib动态代理。静态代理针对特定接口或对象,需手动编码实现;JDK动态代理通过反射机制实现,适用于所有接口;Cglib动态代理则基于字节码技术,无需接口支持,但需引入外部库。每种方法各有优缺点,选择时应根据具体需求考虑。

1.⭐⭐⭐静态代理🌙🌙🌙

  • 基本描述:静态代理代理的是某一个接口的实例对象,以接口的形式对外展示。当然如果不需要以接口的形式对外展示,直接代理对象即可。
  • 缺点:只能代理某一种类型,要想代理其他类型,需要修改代码。
package unittest.proxy;
interface StaticInterface{
   
    void method();
}
class Target implements StaticInterface{
   
    @Override
    public void method() {
   
        System.out.println("StaticInterface");
    }
}
/**
 * @author Dylaniou
 * 基本描述:静态代理代理的是某一个接口的实例对象,以接口的形式对外展示。当然如果不需要以接口的形式对外展示,直接代理对象即可。
 * 缺点:只能代理某一种类型,要想代理其他类型,需要修改代码。
 */
public class JdkStaticProxy implements StaticInterface{
   
    Target target;
    JdkStaticProxy(Target target){
   
        this.target = target;
    }
    @Override
    public void method() {
   
        System.out.println("before");
        target.method();
        System.out.println("after");
    }
    public static void main(String[] args) {
   
        StaticInterface staticInterface = (StaticInterface)(new JdkStaticProxy(new Target()));
        staticInterface.method();
    }
}

2.⭐⭐⭐JDK动态代理🌙🌙🌙

  • 基本描述:jdk动态代理可以代理的接口的实例对象,以接口的形式对外展示。不局限于某个类型。
    • 缺点:必须要有接口。
package unittest.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface DynamicInterface{
   
    void method();
}
class DynamicProxyInterfaceImp implements DynamicInterface{
   
    @Override
    public void method() {
   
        System.out.println("DynamicProxyInterfaceImp");
    }
}
/**
 * @author Dylaniou
 * 基本描述:jdk动态代理可以代理的接口的实例对象,以接口的形式对外展示。不局限于某个类型。
 * 缺点:必须要有接口。
 */
public class JdkDynamicProxy implements InvocationHandler{
   
    Object target;
    JdkDynamicProxy(Object target){
   
        this.target = target;
    }

    public Object getProxyOfTarget(){
   
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
        System.out.println("before");
        method.invoke(target, args);
        System.out.println("after");
        return null;
    }
    public static void main(String[] args) {
   
        DynamicProxyInterfaceImp target = new DynamicProxyInterfaceImp();
        DynamicInterface dynamicInterface = (DynamicInterface)(new JdkDynamicProxy(target)).getProxyOfTarget();
        dynamicInterface.method();
    }
}

3.⭐⭐⭐Cglib动态代理🌙🌙🌙

  • 基本描述:Cglib动态代理可以直接代理实例对象,不是必须要接口。当然想以接口的形式对外展示也是完全OK的。
  • 缺点:Cglib动态代理需要依赖第三方jar包,比如我本地用的就是mybatis-3.5.4里的cglib-3.3.0.jar和asm-7.1.jar。
package unittest.proxy;

import java.lang.reflect.Method;

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

class CglibInstance{
   
    void method(){
   
        System.out.println("CglibInstance");
    };
}
/**
 * @author Dylaniou
 * 基本描述:Cglib动态代理可以直接代理实例对象,不是必须要接口。当然想以接口的形式对外展示也是完全OK的。
 */
//public class CglibProxy{
   
public class CglibProxy implements MethodInterceptor{
   
    public Object getProxyOfTarget(Class cls){
   
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cls);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
   
        System.out.println("before");
         methodProxy.invokeSuper(proxy, args);
        System.out.println("after");
        return null;
    }
    public static void main(String[] args) {
   
        CglibInstance cglibInterface  = (CglibInstance)(new CglibProxy().getProxyOfTarget(CglibInstance.class));
        cglibInterface.method();
        /*Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(CglibInstance.class);
        enhancer.setCallback(new MethodInterceptor(){
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("before");
                Object result = methodProxy.invokeSuper(proxy, args);
                System.out.println("after");
                return result;
            }
        });
        ((CglibInstance) enhancer.create()).method();*/
    }
}
目录
相关文章
|
Java Spring
JDK动态代理和CGLIB动态代理的区别
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理: ● JDK动态代理只提供接口的代理,不支持类的代理Proxy.newProxyInstance(类加载器, 代理对象实现的所有接口, 代理执行器) ● CGLIB是通过继承的方式做的动态代理 , 如果某个类被标记为final,那么它是无法使用 CGLIB做动态代理的。Enhancer.create(父类的字节码对象, 代理执行器)
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类方法的执行。主要通过两种方式实现:JDK动态代理和CGLIB动态代理。JDK动态代理基于接口,利用`java.lang.reflect.Proxy`类和`InvocationHandler`接口;CGLIB则通过字节码技术生成目标类的子类作为代理,适用于未实现接口的类。两者均用于在方法执行前后添加额外逻辑,如日志记录、权限控制等,广泛应用于AOP框架中。
558 2
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类的方法调用,无需修改原代码。它有两种主要实现方式:JDK动态代理和CGLIB动态代理。 - **JDK动态代理**:通过`java.lang.reflect.Proxy`类和`InvocationHandler`接口实现,适用于实现了接口的类。它在方法调用前后插入额外逻辑,如日志记录、权限控制等。 - **CGLIB动态代理**:基于字节码技术,为未实现接口的类生成子类作为代理,重写父类方法以添加增强逻辑。适用于没有接口的类,但要求目标类不能是`final`类或方法。
316 1
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
600 0
探索Java动态代理的奥秘:JDK vs CGLIB
安装JDK18没有JRE环境的解决办法
安装JDK18没有JRE环境的解决办法
1693 141
|
存储 Ubuntu 安全
在Ubuntu 16.04上安装openjdk-6/7/8-jdk的步骤
在整个安装过程中,你可能需要管理员权限,因此你可能要使用 `sudo` 来获取必要的权限。记得做完每一个步骤后,都要检查输出,以确保没有发生错误,并且每项操作都成功完成。如果在安装过程中遇到问题,查看 `/var/log/` 下的日志文件对于问题的解决可能是有帮助的。
839 21
|
IDE Ubuntu Java
在Ubuntu18.04安装兼容JDK 8的Eclipse集成开发环境的指南。
完成以上步骤后,您将在Ubuntu 18.04系统上成功安装并配置了Eclipse IDE,它将与JDK 8兼容,可以开始进行Java开发工作。如果遇到任何问题,请确保每一步骤都正确执行,并检查是否所有路径都与您的具体情况相匹配。
621 11
|
Java 关系型数据库 MySQL
在Linux平台上进行JDK、Tomcat、MySQL的安装并部署后端项目
现在,你可以通过访问http://Your_IP:Tomcat_Port/Your_Project访问你的项目了。如果一切顺利,你将看到那绚烂的胜利之光照耀在你的项目之上!
663 41
|
Oracle Java 关系型数据库
Tomcat和JDK的详细安装、下载和环境配置指南
以上就是JDK和Tomcat的下载、安装和环境配置的详细步骤。希望这个指南能帮助你顺利完成设置。
1004 32
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
916 17