java中代理的实现并在spring的应用

2023-12-26 15:43:29

Java代理机制介绍

Java代理机制是一种在运行时创建一个代理对象来代替原始对象的方法。代理对象通常用于在调用原始对象的方法之前或之后执行一些额外的操作,例如日志记录、性能监控等。

静态代理

静态代理是在编译时就已经确定代理的对象,代理类和原始类是一对一的关系。下面是一个简单的静态代理的例子:

// 定义接口
public interface Hello {
    void sayHello();
}

// 原始类
public class HelloImpl implements Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello, world!");
    }
}

// 代理类
public class HelloProxy implements Hello {
    private Hello hello;

    public HelloProxy(Hello hello) {
        this.hello = hello;
    }

    @Override
    public void sayHello() {
        System.out.println("Before saying hello");
        hello.sayHello();
        System.out.println("After saying hello");
    }
}

动态代理

jdk

动态代理是在运行时创建代理对象,代理类是在运行时生成的。Java提供了java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler来实现动态代理。下面是一个简单的动态代理的例子:

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

// 定义接口
public interface Hello {
    void sayHello();
}

// 原始类
public class HelloImpl implements Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello, world!");
    }
}

// 动态代理类
public class DynamicProxy implements InvocationHandler {
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public Object getProxy() {
        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 saying hello");
        Object result = method.invoke(target, args);
        System.out.println("After saying hello");
        return result;
    }
}

cglib

下面是一个使用CGLIB实现动态代理的示例。

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

import java.lang.reflect.Method;

// 原始类
public class Hello {
    public void sayHello() {
        System.out.println("Hello, world!");
    }
}

// CGLIB动态代理类
public class CglibProxy implements MethodInterceptor {
    private Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }

    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before saying hello");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After saying hello");
        return result;
    }
}

jdk和cglib的区别

区别JDK代理CGLIB代理
实现方式基于接口实现基于继承实现
目标对象必须实现接口可以是普通类或接口实现类
代理性能通常比CGLIB代理慢通常比JDK代理快
适用场景目标对象实现接口的情况目标对象不实现接口或需要继承实现的情况
生成代理对象的方式Proxy.newProxyInstance()CGLIB动态生成子类

Spring中的代理

在Spring中,代理通常用于AOP(面向切面编程)和事务管理。Spring使用代理来实现切面的横切逻辑,并且可以通过配置来选择使用静态代理还是动态代理。

Spring提供了两种代理方式:JDK动态代理和CGLIB动态代理。默认情况下,如果目标对象实现了接口,Spring会使用JDK动态代理;如果目标对象没有实现接口,Spring会使用CGLIB动态代理。

不使用代理的场景

在一些情况下,可能不适合使用代理,例如:

  1. 对性能要求非常高的场景,代理会增加额外的开销。
  2. 原始类本身已经提供了足够的扩展点,不需要额外的代理来实现。

spring中使用代理需要注意的点

在Spring中,代理通常用于AOP事务管理,而在一些特定场景下可能不适合使用代理。这里提出一点,当方法名被private修饰或者使用this调用方法不会生成代理类,这可能会导致事务失效异步任务错误的执行等。

文章来源:https://blog.csdn.net/weixin_44808225/article/details/135221112
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。