设计模式-代理模式详解

代理模式详解

目录


1. 代理模式简介

1.1 定义

代理模式(Proxy Pattern)是一种结构型设计模式,为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在不改变目标对象的情况下,通过代理对象来增强目标对象的功能。

1.2 核心思想

  • 控制访问:代理对象控制对目标对象的访问
  • 功能增强:在不修改目标对象的前提下,增加额外功能
  • 透明性:客户端通过代理对象访问目标对象,感觉不到代理的存在

1.3 适用场景

  • 远程代理:为远程对象提供本地代表
  • 虚拟代理:创建开销大的对象时使用
  • 安全代理:控制对原始对象的访问权限
  • 智能引用:在访问对象时执行额外的操作
  • 缓存代理:为开销大的运算结果提供临时存储

1.4 代理模式分类

静态代理
// 接口
public interface UserService {
    void saveUser(String user);
}

// 目标对象
public class UserServiceImpl implements UserService {
    @Override
    public void saveUser(String user) {
        System.out.println("保存用户: " + user);
    }
}

// 代理对象
public class UserServiceProxy implements UserService {
    private UserService userService;
  
    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }
  
    @Override
    public void saveUser(String user) {
        System.out.println("代理前处理");
        userService.saveUser(user);
        System.out.println("代理后处理");
    }
}
动态代理
  • JDK动态代理:基于接口的动态代理
  • CGLIB动态代理:基于继承的动态代理

2. 核心流程

2.1 静态代理流程

客户端 代理对象 目标对象 调用方法 前置处理 调用目标方法 返回结果 后置处理 返回结果 客户端 代理对象 目标对象

2.2 动态代理流程

JDK动态代理流程
客户端 动态代理对象 调用处理器 目标对象 调用方法 invoke() 前置处理 反射调用目标方法 返回结果 后置处理 返回结果 返回结果 客户端 动态代理对象 调用处理器 目标对象
CGLIB动态代理流程
客户端 CGLIB代理对象 方法拦截器 目标对象 调用方法 intercept() 前置处理 调用父类方法 返回结果 后置处理 返回结果 返回结果 客户端 CGLIB代理对象 方法拦截器 目标对象

2.3 代理模式实现步骤

2.3.1 静态代理实现步骤

步骤1:定义业务接口

// 定义目标对象和代理对象的共同接口
public interface UserService {
    void saveUser(String user);
    void deleteUser(String userId);
    String findUser(String userId);
}

步骤2:实现目标类

// 创建目标对象的具体实现
public class UserServiceImpl implements UserService {
    @Override
    public void saveUser(String user) {
        System.out.println("保存用户: " + user);
        // 模拟数据库操作
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  
    @Override
    public void deleteUser(String userId) {
        System.out.println("删除用户: " + userId);
    }
  
    @Override
    public String findUser(String userId) {
        System.out.println("查找用户: " + userId);
        return "用户信息: " + userId;
    }
}

步骤3:创建静态代理类

// 手动创建代理类,实现相同的接口
public class UserServiceStaticProxy implements UserService {
    private UserService target; // 目标对象
  
    public UserServiceStaticProxy(UserService target) {
        this.target = target;
    }
  
    @Override
    public void saveUser(String user) {
        // 前置处理
        System.out.println("代理前:开始保存用户");
        long startTime = System.currentTimeMillis();
      
        // 调用目标方法
        target.saveUser(user);
      
        // 后置处理
        long endTime = System.currentTimeMillis();
        System.out.println("代理后:保存用户完成,耗时: " + (endTime - startTime) + "ms");
    }
  
    @Override
    public void deleteUser(String userId) {
        System.out.println("代理前:开始删除用户");
        target.deleteUser(userId);
        System.out.println("代理后:删除用户完成");
    }
  
    @Override
    public String findUser(String userId) {
        System.out.println("代理前:开始查找用户");
        String result = target.findUser(userId);
        System.out.println("代理后:查找用户完成");
        return result;
    }
}

步骤4:客户端调用

public class StaticProxyClient {
    public static void main(String[] args) {
        // 创建目标对象
        UserService target = new UserServiceImpl();
      
        // 创建代理对象
        UserService proxy = new UserServiceStaticProxy(target);
      
        // 通过代理对象调用方法
        proxy.saveUser("张三");
        proxy.deleteUser("001");
        String user = proxy.findUser("001");
        System.out.println("查找结果: " + user);
    }
}
2.3.2 JDK动态代理实现步骤

步骤1:定义业务接口(同上)

步骤2:实现目标类(同上)

步骤3:创建调用处理器

// 实现InvocationHandler接口
public class UserServiceInvocationHandler implements InvocationHandler {
    private Object target; // 目标对象
  
    public UserServiceInvocationHandler(Object target) {
        this.target = target;
    }
  
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置处理
        System.out.println("动态代理前:调用方法 " + method.getName());
        long startTime = System.currentTimeMillis();
      
        // 通过反射调用目标方法
        Object result = method.invoke(target, args);
      
        // 后置处理
        long endTime = System.currentTimeMillis();
        System.out.println("动态代理后:方法 " + method.getName() + " 执行完成,耗时: " + (endTime - startTime) + "ms");
      
        return result;
    }
}

步骤4:创建动态代理工厂

// 动态代理工厂类
public class DynamicProxyFactory {
    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(), // 类加载器
            target.getClass().getInterfaces(),   // 接口数组
            new UserServiceInvocationHandler(target) // 调用处理器
        );
    }
  
    // 泛型版本,提供类型安全
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target, Class<T> interfaceClass) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            new Class<?>[]{interfaceClass},
            new UserServiceInvocationHandler(target)
        );
    }
}

步骤5:客户端调用

public class DynamicProxyClient {
    public static void main(String[] args) {
        // 创建目标对象
        UserService target = new UserServiceImpl();
      
        // 创建动态代理对象
        UserService proxy = (UserService) DynamicProxyFactory.createProxy(target);
      
        // 通过代理对象调用方法
        proxy.saveUser("李四");
        proxy.deleteUser("002");
        String user = proxy.findUser("002");
        System.out.println("查找结果: " + user);
      
        // 使用泛型版本
        UserService proxy2 = DynamicProxyFactory.createProxy(target, UserService.class);
        proxy2.saveUser("王五");
    }
}
2.3.3 CGLIB动态代理实现步骤

步骤1:添加CGLIB依赖

<!-- Maven依赖 -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

步骤2:实现目标类(不需要接口)

// 目标类,不需要实现接口
public class UserServiceCglib {
    public void saveUser(String user) {
        System.out.println("CGLIB保存用户: " + user);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  
    public void deleteUser(String userId) {
        System.out.println("CGLIB删除用户: " + userId);
    }
  
    public String findUser(String userId) {
        System.out.println("CGLIB查找用户: " + userId);
        return "CGLIB用户信息: " + userId;
    }
}

步骤3:创建方法拦截器

// 实现MethodInterceptor接口
public class UserServiceMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 前置处理
        System.out.println("CGLIB代理前:调用方法 " + method.getName());
        long startTime = System.currentTimeMillis();
      
        // 调用目标方法(使用MethodProxy,性能更好)
        Object result = proxy.invokeSuper(obj, args);
      
        // 后置处理
        long endTime = System.currentTimeMillis();
        System.out.println("CGLIB代理后:方法 " + method.getName() + " 执行完成,耗时: " + (endTime - startTime) + "ms");
      
        return result;
    }
}

步骤4:创建CGLIB代理工厂

// CGLIB代理工厂类
public class CglibProxyFactory {
    public static Object createProxy(Class<?> targetClass) {
        // 创建Enhancer对象
        Enhancer enhancer = new Enhancer();
      
        // 设置父类
        enhancer.setSuperclass(targetClass);
      
        // 设置回调
        enhancer.setCallback(new UserServiceMethodInterceptor());
      
        // 创建代理对象
        return enhancer.create();
    }
  
    // 泛型版本
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(Class<T> targetClass, Class<T> interfaceClass) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetClass);
        enhancer.setInterfaces(new Class<?>[]{interfaceClass});
        enhancer.setCallback(new UserServiceMethodInterceptor());
        return (T) enhancer.create();
    }
}

步骤5:客户端调用

public class CglibProxyClient {
    public static void main(String[] args) {
        // 创建CGLIB代理对象
        UserServiceCglib proxy = (UserServiceCglib) CglibProxyFactory.createProxy(UserServiceCglib.class);
      
        // 通过代理对象调用方法
        proxy.saveUser("赵六");
        proxy.deleteUser("003");
        String user = proxy.findUser("003");
        System.out.println("查找结果: " + user);
    }
}
2.3.4 通用代理工具类

创建统一的代理工具类

// 通用代理工具类
public class ProxyUtils {
  
    /**
     * 创建代理对象(自动选择代理方式)
     */
    public static Object createProxy(Object target) {
        if (target.getClass().getInterfaces().length > 0) {
            // 有接口,使用JDK动态代理
            return createJdkProxy(target);
        } else {
            // 无接口,使用CGLIB动态代理
            return createCglibProxy(target);
        }
    }
  
    /**
     * 创建JDK动态代理
     */
    public static Object createJdkProxy(Object target) {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return handleMethod(target, method, args);
                }
            }
        );
    }
  
    /**
     * 创建CGLIB动态代理
     */
    public static Object createCglibProxy(Object target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                return handleMethod(target, method, args);
            }
        });
        return enhancer.create();
    }
  
    /**
     * 统一的方法处理逻辑
     */
    private static Object handleMethod(Object target, Method method, Object[] args) throws Throwable {
        System.out.println("代理前:调用方法 " + method.getName());
        long startTime = System.currentTimeMillis();
      
        Object result = method.invoke(target, args);
      
        long endTime = System.currentTimeMillis();
        System.out.println("代理后:方法 " + method.getName() + " 执行完成,耗时: " + (endTime - startTime) + "ms");
      
        return result;
    }
}

使用通用工具类

public class UniversalProxyClient {
    public static void main(String[] args) {
        // 测试有接口的目标对象
        UserService userService = new UserServiceImpl();
        UserService userProxy = (UserService) ProxyUtils.createProxy(userService);
        userProxy.saveUser("通用代理用户");
      
        // 测试无接口的目标对象
        UserServiceCglib userServiceCglib = new UserServiceCglib();
        UserServiceCglib cglibProxy = (UserServiceCglib) ProxyUtils.createProxy(userServiceCglib);
        cglibProxy.saveUser("通用代理CGLIB用户");
    }
}
2.3.5 实现步骤总结
代理类型步骤1步骤2步骤3步骤4步骤5
静态代理定义接口实现目标类手动创建代理类实现代理逻辑客户端调用
JDK动态代理定义接口实现目标类创建InvocationHandler使用Proxy.newProxyInstance客户端调用
CGLIB动态代理无需接口实现目标类创建MethodInterceptor使用Enhancer.create客户端调用

关键要点:

  1. 静态代理:需要手动编写代理类,但性能最好
  2. JDK动态代理:需要接口,使用反射调用
  3. CGLIB动态代理:不需要接口,使用字节码技术
  4. 选择策略:有接口用JDK,无接口用CGLIB,性能要求高用静态代理

3. 重难点分析

3.1 重难点一:动态代理的实现原理

难点分析
  • 字节码生成:动态代理需要在运行时生成字节码
  • 反射机制:需要理解Java反射的工作原理
  • 类加载机制:动态生成的类需要被正确加载
解决方案
// JDK动态代理实现
public class DynamicProxyExample {
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
      
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                @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;
                }
            }
        );
      
        proxy.saveUser("张三");
    }
}

3.2 重难点二:JDK动态代理 vs CGLIB动态代理

对比分析
特性JDK动态代理CGLIB动态代理
基于接口继承
性能较慢(反射调用)较快(直接调用)
限制必须有接口目标类不能是final
依赖JDK自带需要第三方库
生成方式接口实现子类继承
选择策略
// 选择策略示例
public class ProxyFactory {
    public static Object createProxy(Object target) {
        // 如果有接口,使用JDK动态代理
        if (target.getClass().getInterfaces().length > 0) {
            return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new MyInvocationHandler(target)
            );
        } else {
            // 否则使用CGLIB动态代理
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(new MyMethodInterceptor(target));
            return enhancer.create();
        }
    }
}

3.3 重难点三:代理模式的性能优化

性能问题
  • 反射调用开销:JDK动态代理使用反射,性能较低
  • 字节码生成开销:动态生成类需要时间
  • 内存占用:代理类会占用额外内存
优化策略
// 1. 缓存代理对象
public class ProxyCache {
    private static final Map<Class<?>, Object> proxyCache = new ConcurrentHashMap<>();
  
    public static Object getProxy(Object target) {
        return proxyCache.computeIfAbsent(target.getClass(), 
            clazz -> createProxy(target));
    }
}

// 2. 使用CGLIB的FastClass机制
public class FastClassExample {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserServiceImpl.class);
        enhancer.setCallback(new FastClassInterceptor());
        enhancer.setUseFastClass(true); // 启用FastClass
        UserService proxy = (UserService) enhancer.create();
    }
}

4. Spring中的源码分析

4.1 Spring AOP中的代理实现

核心接口分析
// Spring AOP核心接口
public interface AopProxy {
    Object getProxy();
    Object getProxy(ClassLoader classLoader);
}

// JDK动态代理实现
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    private final AdvisedSupport advised;
  
    @Override
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }
  
    @Override
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
}
CGLIB动态代理实现
// CGLIB动态代理实现
class CglibAopProxy implements AopProxy, Serializable {
    private final AdvisedSupport advised;
  
    @Override
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }
  
    @Override
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
        }
      
        try {
            Class<?> rootClass = this.advised.getTargetClass();
            if (rootClass == null) {
                throw new AopConfigException("Target class cannot be null");
            }
          
            Class<?> proxySuperClass = rootClass;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }
          
            // 验证类
            validateClassIfNecessary(proxySuperClass, classLoader);
          
            // 配置CGLIB增强器
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                    ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
          
            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            enhancer.setCallbacks(callbacks);
            enhancer.setCallbackTypes(types);
          
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + 
                this.advised.getTargetClass() + ": " + ex.getMessage(), ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }
}

4.2 Spring代理选择策略

DefaultAopProxyFactory源码分析
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
  
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                    "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }
  
    /**
     * 判断是否没有用户提供的代理接口
     */
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    }
}
代理选择规则
  1. 强制使用CGLIBproxyTargetClass = true
  2. 优化模式optimize = true
  3. 无接口:目标类没有实现接口
  4. 默认策略:有接口使用JDK,无接口使用CGLIB

4.3 Spring AOP执行流程

核心执行流程
// JdkDynamicAopProxy的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
  
    TargetSource targetSource = this.advised.targetSource;
    Object target = null;
  
    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // 处理equals方法
            return equals(args[0]);
        }
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // 处理hashCode方法
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // 处理DecoratingProxy接口
            return AopProxyUtils.advisedTarget(this.advised);
        }
      
        Object retVal;
      
        if (this.advised.exposeProxy) {
            // 暴露代理对象到ThreadLocal
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
      
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
      
        // 获取拦截器链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      
        if (chain.isEmpty()) {
            // 没有拦截器,直接调用目标方法
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // 创建方法调用对象,执行拦截器链
            MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            retVal = invocation.proceed();
        }
      
        // 处理返回值
        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target &&
            returnType != Object.class && returnType.isAssignableFrom(targetClass)) {
            retVal = target;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                "Null return value from advice does not match primitive return type for: " + method);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

5. 面试高频点

5.1 基础概念类问题

Q1: 什么是代理模式?有哪些类型?

答案要点:

  • 代理模式是一种结构型设计模式
  • 为其他对象提供代理以控制访问
  • 类型:静态代理、动态代理(JDK、CGLIB)
Q2: 静态代理和动态代理的区别?

答案要点:

  • 静态代理:编译时确定,需要手动编写代理类
  • 动态代理:运行时生成,通过反射或字节码技术
  • 性能:静态代理性能更好,动态代理更灵活

5.2 实现原理类问题

Q3: JDK动态代理的实现原理?

答案要点:

// 核心实现步骤
1. 通过Proxy.newProxyInstance()创建代理对象
2. 代理对象实现目标接口
3. 所有方法调用都转发到InvocationHandler.invoke()
4.invoke()方法中通过反射调用目标方法
Q4: CGLIB动态代理的实现原理?

答案要点:

// 核心实现步骤
1. 通过Enhancer创建代理类
2. 代理类继承目标类
3. 重写目标方法,添加拦截逻辑
4. 使用MethodInterceptor处理方法调用

5.3 Spring AOP类问题

Q5: Spring AOP使用哪种代理方式?

答案要点:

  • 默认策略:有接口用JDK,无接口用CGLIB
  • 强制CGLIB:设置 proxyTargetClass = true
  • 选择依据:目标类是否有接口、是否强制使用CGLIB
Q6: Spring AOP的执行流程?

答案要点:

1. 创建代理对象(JdkDynamicAopProxyCglibAopProxy2. 方法调用时进入invoke()方法
3. 获取拦截器链(Advisor链)
4. 创建MethodInvocation对象
5. 执行拦截器链(责任链模式)
6. 调用目标方法
7. 返回结果

5.4 性能优化类问题

Q7: 如何优化动态代理的性能?

答案要点:

  • 缓存代理对象:避免重复创建
  • 使用CGLIB:比JDK动态代理性能更好
  • 减少反射调用:使用FastClass机制
  • 合理使用:避免过度使用代理
Q8: 代理模式有什么缺点?

答案要点:

  • 性能开销:反射调用和字节码生成
  • 内存占用:代理类占用额外内存
  • 调试困难:代理对象增加调试复杂度
  • 限制条件:CGLIB不能代理final类

5.5 实际应用类问题

Q9: 在项目中如何选择代理方式?

答案要点:

// 选择策略
if (有接口 && 不需要强制CGLIB) {
    使用JDK动态代理;
} else if (无接口 || 强制CGLIB) {
    使用CGLIB动态代理;
} else if (性能要求极高) {
    考虑静态代理;
}
Q10: 如何实现一个简单的AOP框架?

答案要点:

// 核心组件
1. 切面定义:@Aspect注解
2. 切点定义:@Pointcut注解
3. 通知定义:@Before@After4. 代理工厂:创建代理对象
5. 拦截器链:执行切面逻辑

5.6 源码分析类问题

Q11: Spring如何选择代理方式?

答案要点:

// DefaultAopProxyFactory.createAopProxy()
if (config.isOptimize() || 
    config.isProxyTargetClass() || 
    hasNoUserSuppliedProxyInterfaces(config)) {
    // 使用CGLIB
    return new ObjenesisCglibAopProxy(config);
} else {
    // 使用JDK动态代理
    return new JdkDynamicAopProxy(config);
}
Q12: 代理对象是如何创建的?

答案要点:

  • JDK:通过 Proxy.newProxyInstance()创建
  • CGLIB:通过 Enhancer.create()创建
  • Spring:通过 AopProxyFactory统一创建

总结

代理模式是Java开发中非常重要的设计模式,特别是在Spring AOP中广泛应用。掌握代理模式的原理、实现方式和在Spring中的应用,对于理解AOP机制和提升代码质量具有重要意义。

关键要点

  1. 理解原理:掌握静态代理和动态代理的实现原理
  2. 区分场景:知道什么时候使用哪种代理方式
  3. 性能考虑:了解代理模式的性能影响和优化方法
  4. Spring集成:理解Spring AOP中代理模式的应用
  5. 实际应用:能够在项目中合理使用代理模式

通过深入学习代理模式,可以更好地理解面向切面编程的思想,提升代码的可维护性和扩展性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值