JDK动态代理

Java中的两种常用动态代理方式

JDK动态代理和Cglib动态代理是Java中常用的实现动态代理的方式。它们都可以在运行时生成代理类,实现对目标对象的代理操作。

JDK动态代理适用于接口代理,Cglib动态代理适用于类代理。

Cglib动态代理

Cglib动态代理是基于继承的动态代理方式。它通过生成目标类的子类来实现代理,子类重写了目标类的方法,并在方法中添加了代理逻辑。


JDK动态代理

JDK动态代理是Java提供的一种基于接口的动态代理方式。它通过反射机制在运行时动态生成代理类,代理类实现了目标接口,并且将方法的调用委托给InvocationHandler接口的实现类来处理。

  1. 基于接口的动态代理示例代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

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

// 实现接口的类
class HelloImpl implements Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello, World!");
    }
}

// 实现InvocationHandler接口
class DynamicProxy implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method invocation");
        Object result = method.invoke(target, args);
        System.out.println("After method invocation");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Hello hello = new HelloImpl();
        InvocationHandler handler = new DynamicProxy(hello);
        Hello proxy = (Hello) Proxy.newProxyInstance(
                hello.getClass().getClassLoader(),
                hello.getClass().getInterfaces(),
                handler);
        proxy.sayHello();
    }
}
  1. 基于类的动态代理示例代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义类
class Hello {
    public void sayHello() {
        System.out.println("Hello, World!");
    }
}

// 实现InvocationHandler接口
class DynamicProxy implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method invocation");
        Object result = method.invoke(target, args);
        System.out.println("After method invocation");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Hello hello = new Hello();
        InvocationHandler handler = new DynamicProxy(hello);
        Hello proxy = (Hello) Proxy.newProxyInstance(
                hello.getClass().getClassLoader(),
                hello.getClass().getInterfaces(),
                handler);
        proxy.sayHello();
    }
}

Java动态代理中,通过Proxy.newProxyInstance()方法创建代理对象时,需传三个参数:

  1. 类加载器(ClassLoader):用来加载目标类和代理类的类加载器。一般情况下,可以使用目标类的类加载器来加载代理类。

  2. 接口数组(Class[] interfaces):代理类需要实现的接口数组。代理对象会实现这些接口,并且可以调用接口中定义的方法。

  3. 调用处理器(InvocationHandler):一个实现了InvocationHandler接口的对象,用来处理代理对象的方法调用。在调用代理对象的方法时,会触发调用处理器的invoke()方法。

第一个参数的类加载器可以传递目标类的类加载器,也可以传递实现了 InvocationHandler 接口的对象的类加载器。但是,为了确保代理类能够访问目标类的方法和属性,通常建议传递目标类的类加载器。

如果接口没有实现类时,该使用场景为,工具类中提供了注解,在服务的接口的方法上,通过使用工具类中的注解就能执行接口方法,而不需要定义接口的实现类。

//服务中有接口
public interface AInter {
	public void insetStudent(Student stu);
}
//如何想要AInter能被代理,可把AInter注入到spring中,返回值为代理后的对象,这样@Autowire拿到的就是代理对象,调用AInter中的方法时,走的就是代理对象里面的逻辑

//配置类
@Configuration
public class Config {
	@Bean
	public AInter doProxy () {
		return Util.myProxy(AInter.class)l
	}
}

//service层
pubic class StuService {
	@Autowire
	AInter aInter;
}


------------------------------------------------------
//工具类 
public class Util() {
	public <T> T myProxy(Class<T> classPro){
	MyHandle handler = new MyHandle(classPro);
	 T proxy = (T) Proxy.newProxyInstance(
	                handler.getClass().getClassLoader(),
	                new Class<?>[] {classPro},
	                handler);
	}
	return proxy;
}

//实现InvocationHandler接口的类
public class MyHandle implements InvocationHandler{
   private Type target;

    public MyHandle(Type target) {
        this.target = target;
    }
}

第一个参数可传入实现了InvocationHandler接口的对象类加载器,第二个参数可直接传入这个接口的数组,第三个参数传实现InvocationHandler接口的对象。

你可能感兴趣的:(java,开发语言)