实现AOP(Aspect-Oriented Programming)以及其他功能

简介: 实现AOP(Aspect-Oriented Programming)以及其他功能

CGLIB(Code Generation Library)是一个代码生成库,主要用于为Java对象提供动态代理。Spring框架在某些情况下使用CGLIB来创建代理对象,以实现AOP(Aspect-Oriented Programming)以及其他功能。

 

CGLIB代理简介

 

CGLIB通过生成目标类的子类来创建代理对象。这与标准的Java动态代理(`java.lang.reflect.Proxy`)不同,后者要求目标类必须实现接口。CGLIB可以代理任何普通的类,而不仅仅是接口。

 

Spring 使用 CGLIB 代理的场景

 

在Spring中,默认情况下,AOP代理会优先使用JDK动态代理。如果目标对象没有实现任何接口,Spring会退而求其次使用CGLIB来生成代理对象。

 

具体来说,Spring使用CGLIB代理的场景包括但不限于以下几个:

 

1. **没有实现接口的类**:当一个类没有实现任何接口时,Spring无法使用JDK动态代理,只能使用CGLIB。

2. **强制使用CGLIB**:即使目标类实现了接口,也可以使用`@EnableAspectJAutoProxy(proxyTargetClass = true)`注解强制Spring使用CGLIB代理。

3. **配置类代理**:Spring为了支持@Configuration类中的@Bean方法调用,通常会使用CGLIB代理这些配置类。

 

CGLIB代理的原理

 

CGLIB通过字节码操作来生成代理类,并在运行时加载该类。它使用ASM库直接生成新的类文件,这使得其性能比反射方式更高。以下是CGLIB代理的大致工作流程:

 

1. **动态生成子类**:CGLIB生成目标类的子类,并覆盖目标类中的方法。

2. **方法拦截**:在代理方法中,CGLIB添加拦截器逻辑,用于在方法调用前后执行特定的拦截器行为。

3. **调用父类方法**:代理方法内部会调用父类(即目标类)的方法,从而实现对原方法的调用。

 

深入源码

 

下面我们通过查看Spring AOP部分源码,深入理解Spring是如何使用CGLIB实现代理的。

 

`ProxyFactory` 类

 

`ProxyFactory`是Spring AOP框架中用于创建代理对象的重要类。它根据目标对象是否实现接口选择合适的代理策略。

 

```java
public class ProxyFactory extends AdvisedSupport implements AopProxyFactory {
    // 省略其他代码...
 
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            return new CglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }
 
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] interfaces = config.getProxiedInterfaces();
        return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.isAssignableFrom(interfaces[0])));
    }
}
```

 

在上面的代码中,如果`isProxyTargetClass()`返回true,或者目标类没有实现任何接口,`createAopProxy`方法会返回一个`CglibAopProxy`实例。

 

`CglibAopProxy` 类

 

`CglibAopProxy`类负责使用CGLIB创建代理对象。

 

```java
public class CglibAopProxy implements AopProxy, Serializable {
    // 省略其他代码...
 
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
        }
        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
 
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
            }
            enhancer.setSuperclass(rootClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised));
            enhancer.setCallbacks(getCallbacks(rootClass));
 
            return createProxyClassAndInstance(enhancer, rootClass);
        }
        catch (CodeGenerationException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: Common causes of this problem include using a final class or a non-visible class", ex);
        }
        catch (IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: Common causes of this problem include using a final class or a non-visible class", ex);
        }
    }
 
    protected Enhancer createEnhancer() {
        return new Enhancer();
    }
 
    protected Object createProxyClassAndInstance(Enhancer enhancer, Class<?> rootClass) {
        enhancer.setInterceptDuringConstruction(false);
        Object proxy = enhancer.create();
        return proxy;
    }
 
    // 省略其他代码...
}
```

 

在上面的代码中,`getProxy`方法使用CGLIB的`Enhancer`类来创建代理对象。`Enhancer`是CGLIB的核心类,用于生成代理类。

 

`Enhancer` 类

 

`Enhancer`类是CGLIB库中的核心类,它负责生成代理类。通过设置回调和过滤器,`Enhancer`可以指定代理对象的行为。

 

```java
public class Enhancer {
    // 省略其他代码...
 
    public Object create() {
        // 创建并返回代理对象
        return createHelper().create();
    }
 
    private Generator createHelper() {
        Generator g = new Generator();
        g.setSuperclass(superclass);
        g.setInterfaces(interfaces);
        g.setCallbacks(callbacks);
        g.setCallbackFilter(filter);
        g.setNamingPolicy(namingPolicy);
        g.setStrategy(strategy);
        return g;
    }
 
    // 省略其他代码...
}
```

 

在上面的代码中,`create`方法最终调用`Generator`类生成代理对象。

 

总结

 

CGLIB代理在Spring框架中扮演了重要的角色,特别是在AOP和配置类代理方面。通过动态生成目标类的子类,CGLIB能够在运行时创建代理对象,并实现方法拦截和增强。理解CGLIB代理的工作原理和Spring中相关源码,可以帮助我们更好地掌握Spring框架的内部机制,提高调试和优化能力。

目录
相关文章
|
10天前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
28 1
|
3月前
|
缓存 监控 安全
AOP则关注如何将那些影响多个类的功能模块化
AOP则关注如何将那些影响多个类的功能模块化
|
19天前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
【9月更文挑战第9天】AOP(面向切面编程)通过分离横切关注点提高模块化程度,如日志记录、事务管理等。Micronaut AOP基于动态代理机制,在应用启动时为带有特定注解的类生成代理对象,实现在运行时拦截方法调用并执行额外逻辑。通过简单示例展示了如何在不修改 `CalculatorService` 类的情况下记录 `add` 方法的参数和结果,仅需添加 `@Loggable` 注解即可。这不仅提高了代码的可维护性和可扩展性,还降低了引入新错误的风险。
36 13
|
3月前
|
缓存 监控 安全
在 Spring Boot 中使用 AOP(Aspect-Oriented Programming)实现日志记录功能
在 Spring Boot 中使用 AOP(Aspect-Oriented Programming)实现日志记录功能
122 1
|
4月前
|
Java 数据格式 Spring
利用AOP实现统一功能处理
利用AOP实现统一功能处理
36 2
|
4月前
|
XML Java 数据格式
使用Spring AOP添加统计时间的功能
使用Spring AOP添加统计时间的功能
|
Java API 数据安全/隐私保护
一张思维导图带你学会SpringBoot使用AOP实现日志管理功能
一张思维导图带你学会SpringBoot使用AOP实现日志管理功能
154 0
|
Java Spring
Spring AOP统一功能处理(切面、切点、连接点、通知)(下)
Spring AOP统一功能处理(切面、切点、连接点、通知)(下)
130 0
|
前端开发 Java Maven
Spring AOP统一功能处理(切面、切点、连接点、通知)(上)
Spring AOP统一功能处理(切面、切点、连接点、通知)(上)
235 0
|
前端开发 Java 数据安全/隐私保护
Spring AOP【用户登陆统一验证功能】
Spring AOP【用户登陆统一验证功能】
Spring AOP【用户登陆统一验证功能】