怎么也记不住的八股

2024-10-18

Java代理模式

使用代理对象来代替真正的目标对象,既能实现原有目标对象的功能,还能在不修改目标对象的情况下,增加额外的功能。

静态代理

每一个目标类对应一个代理类,当目标类新增方法时,代理类也需要新增一个方法,每个方法的增强都是手动完成的

步骤:

  • 创建一个接口和对应的实现类
  • 创建一个代理类同样实现这个接口
  • 将目标类注入代理类,调用目标类的方法

JDK动态代理

Java中的动态代理是一种在运行时创建代理对象的机制,动态代理允许程序在运行是决定代理对象的行为,而不需要在编译时确定。

工作原理:

  • 代理接口:定义一个接口,代理对象和目标对象都实现这个接口
  • 创建一个类实现InvocationHandler接口:在java中,使用InvocationHandler接口来定义代理行为,需要实现这个接口并且重写接口的invoke方法,该方法在调用真实对象的时候会触发
  • Proxy类,使用java的Proxy类的newProxyInstance方法来动态创建动态代理对象。
  1. 定义接口
public interface UserService {
    void addUser(String user);
}
  1. 实现接口
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String user) {
        System.out.println("添加用户: " + user);
    }
}
  1. 创建InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxyHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 代理前的处理
        System.out.println("代理前的处理...");

        // 调用真实对象的方法
        Object result = method.invoke(target, args);

        // 代理后的处理
        System.out.println("代理后的处理...");
        
        return result;
    }
}
  1. 创建代理对象
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        
        // 创建代理对象
        UserService proxyInstance = (UserService) Proxy.newProxyInstance(
            userService.getClass().getClassLoader(),
            userService.getClass().getInterfaces(),
            new DynamicProxyHandler(userService)
        );

        // 使用代理对象
        proxyInstance.addUser("张三");
    }
}

CGLIB动态代理

JDK动态代理有一个致命的问题,就是只能代理实现了接口的类

CGLIB基于ASM字节码生成工具,通过继承的方式来实现代理类,所以不需要接口,可以代理普通的类

工作原理:

CGLIB通过继承目标类来创建一个子类,并重写方法,在方法调用前后插入自己的逻辑

步骤:

  • 添加CHLIB依赖
  • 创建目标类
  • 创建MethodInterceptor:实现MethodInterceptor接口,重写intercept方法以定义代理行为。
  • 创建代理对象:使用CGLIB的Enhancer类来创建代理对象

1.

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

2.

public class UserService {
    public void addUser(String user) {
        System.out.println("添加用户: " + user);
    }
}

3.

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

public class UserServiceInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 代理前的处理
        System.out.println("代理前的处理...");

        // 调用目标类的方法
        Object result = proxy.invokeSuper(obj, args);

        // 代理后的处理
        System.out.println("代理后的处理...");

        return result;
    }
}

4.

import net.sf.cglib.proxy.Enhancer;

public class Main {
    public static void main(String[] args) {
        // 创建CGLIB的Enhancer对象
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class); // 设置需要代理的目标类
        enhancer.setCallback(new UserServiceInterceptor()); // 设置代理逻辑

        // 创建代理对象
        UserService proxyInstance = (UserService) enhancer.create();

        // 使用代理对象
        proxyInstance.addUser("李四");
    }
}