## MetadataAwareAspectInstanceFactory - [MetadataAwareAspectInstanceFactory](#metadataawareaspectinstancefactory) - [一、基本信息](#一基本信息) - [二、基本描述](#二基本描述) - [三、主要功能](#三主要功能) - [四、接口源码](#四接口源码) - [五、主要实现](#五主要实现) - [六、类关系图](#六类关系图) - [七、最佳实践](#七最佳实践) - [八、源码分析](#八源码分析) ### 一、基本信息 ✒️ **作者** - Lex 📝 **博客** - [掘金](https//juejin.cn/user/4251135018533068/posts) 📚 **源码地址** - [github](https//github.com/xuchengsheng/spring-reading) ### 二、基本描述 `MetadataAwareAspectInstanceFactory` 接口是 Spring AOP 中的关键接口,用于实例化切面并处理其元数据信息,为 Spring 框架提供了对 AspectJ 注解风格的 AOP 切面的支持。 ### 三、主要功能 1. **实例化切面** + 通过 `getAspectInstance()` 方法,提供切面实例,以便在运行时应用切面的通知。 2. **处理元数据信息** + 通过 `getAspectMetadata()` 方法,获取切面类的元数据信息,如类名、所属的类、切点表达式等,以便在运行时能够正确地应用切面。 3. **支持 AspectJ 注解风格的 AOP** + 通过这个接口,Spring AOP 能够实现对 AspectJ 注解风格的 AOP 切面的实例化和元数据处理,从而支持在 Spring 应用中使用 AspectJ 注解定义切面。 ### 四、接口源码 `MetadataAwareAspectInstanceFactory` 接口是 `AspectInstanceFactory` 的子接口,用于返回与 AspectJ 注解类关联的 `AspectMetadata`。`AspectMetadata` 包含与切面相关的元数据信息。此接口还定义了一个方法 `getAspectCreationMutex()`,用于返回此工厂的最佳创建互斥锁。由于 `AspectMetadata` 使用了 Java 5 专用的 `org.aspectj.lang.reflect.AjType`,因此需要将此方法拆分到这个子接口中。 ```java /** * {@link org.springframework.aop.aspectj.AspectInstanceFactory} 的子接口,用于返回与 AspectJ 注解类关联的 {@link AspectMetadata}。 * *
理想情况下,AspectInstanceFactory 本身应该包括此方法,但由于 AspectMetadata 使用了 Java 5 专用的 {@link org.aspectj.lang.reflect.AjType},
* 我们需要拆分出这个子接口。
*
* @author Rod Johnson
* @since 2.0
* @see AspectMetadata
* @see org.aspectj.lang.reflect.AjType
*/
public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactory {
/**
* 返回此工厂的切面的 AspectJ AspectMetadata。
* @return 切面元数据
*/
AspectMetadata getAspectMetadata();
/**
* 返回此工厂的最佳创建互斥锁。
* @return 互斥锁对象(如果不需要使用锁,则可能为 {@code null})
* @since 4.3
*/
@Nullable
Object getAspectCreationMutex();
}
```
### 五、主要实现
1. **SimpleMetadataAwareAspectInstanceFactory**
- 这个实现类是最简单的一种,它用于创建单例的切面实例。它简单地实例化切面类,并提供其实例作为切面的实例。
2. **SingletonMetadataAwareAspectInstanceFactory**
- 与 `SimpleMetadataAwareAspectInstanceFactory` 类似,这个实现类也用于创建单例的切面实例,但是它可以与 Spring 的容器集成,以便将切面实例作为容器中的单例 bean 进行管理。
3. **BeanFactoryAspectInstanceFactory**
- 这个实现类与 Spring 的 BeanFactory 集成,它用于创建切面实例,并且能够处理切面类的依赖注入。它可以在切面类中注入其他 Spring 管理的 bean,实现更复杂的业务逻辑。
4. **PrototypeAspectInstanceFactory**
- 这个实现类用于创建原型(prototype)的切面实例。与单例不同,原型实例每次请求时都会创建一个新的实例,适用于需要在每次使用时都重新创建实例的场景。
5. **LazySingletonAspectInstanceFactoryDecorator**
- 这个实现类是一个装饰器,用于延迟初始化单例的切面实例。它在首次请求切面实例时才进行实例化,以提高性能并延迟资源消耗。
### 六、类关系图
~~~mermaid
classDiagram
direction BT
class AspectInstanceFactory {
< 注意,如果使用原型模式可能会多次实例化,这可能不会得到您期望的语义。
* 使用 {@link LazySingletonAspectInstanceFactoryDecorator} 来包装这个工厂,
* 以确保只返回一个新的切面。
*
* 作者:Rod Johnson, Juergen Hoeller
* @since 2.0
* @see org.springframework.beans.factory.BeanFactory
* @see LazySingletonAspectInstanceFactoryDecorator
*/
@SuppressWarnings("serial")
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory, Serializable {
private final BeanFactory beanFactory; // Bean 工厂
private final String name; // Bean 名称
private final AspectMetadata aspectMetadata; // 切面的元数据信息
/**
* 创建一个 BeanFactoryAspectInstanceFactory。AspectJ 将被调用来自省,
* 使用从 BeanFactory 中为给定的 bean 名称返回的类型创建 AJType 元数据。
*
* @param beanFactory BeanFactory,用于获取实例
* @param name bean 的名称
*/
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
this(beanFactory, name, null);
}
/**
* 创建一个 BeanFactoryAspectInstanceFactory,提供一个类型,AspectJ 应该自省以创建 AJType 元数据。
* 如果 BeanFactory 可能将类型视为子类(例如使用 CGLIB),并且信息应该与超类相关,则使用此选项。
*
* @param beanFactory BeanFactory,用于获取实例
* @param name bean 的名称
* @param type AspectJ 应该自省的类型({@code null} 表示通过 bean 名称解析通过 {@link BeanFactory#getType} 的类型)
*/
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, @Nullable Class> type) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
Assert.notNull(name, "Bean name must not be null");
this.beanFactory = beanFactory;
this.name = name;
Class> resolvedType = type;
if (type == null) {
resolvedType = beanFactory.getType(name);
Assert.notNull(resolvedType, "Unresolvable bean type - explicitly specify the aspect class");
}
this.aspectMetadata = new AspectMetadata(resolvedType, name); // 创建切面的元数据信息
}
/**
* 获取切面实例。
*
* @return 切面实例
*/
@Override
public Object getAspectInstance() {
return this.beanFactory.getBean(this.name);
}
/**
* 获取切面的类加载器。
*
* @return 切面的类加载器
*/
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
}
/**
* 获取切面的元数据信息。
*
* @return 切面的元数据信息
*/
@Override
public AspectMetadata getAspectMetadata() {
return this.aspectMetadata;
}
/**
* 获取切面实例的创建锁。
*
* @return 切面实例的创建锁
*/
@Override
@Nullable
public Object getAspectCreationMutex() {
if (this.beanFactory.isSingleton(this.name)) {
// 依赖于工厂提供的单例语义 -> 没有本地锁。
return null;
} else if (this.beanFactory instanceof ConfigurableBeanFactory) {
// 从工厂中没有单例保证 -> 让我们本地锁定,但重用工厂的单例锁,以防万一我们的通知 bean 的惰性依赖项
// 不小心触发了单例锁隐式...
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
} else {
return this;
}
}
/**
* 确定此工厂目标切面的顺序,可以通过实现 {@link org.springframework.core.Ordered} 接口来表达实例特定的顺序
* (仅对单例 bean 进行检查),也可以通过 {@link org.springframework.core.annotation.Order} 注解在类级别表达顺序。
*
* @see org.springframework.core.Ordered
* @see org.springframework.core.annotation.Order
*/
@Override
public int getOrder() {
Class> type = this.beanFactory.getType(this.name);
if (type != null) {
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
}
return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE);
}
return Ordered.LOWEST_PRECEDENCE;
}
@Override
public String toString() {
return getClass().getSimpleName() + ": bean name '" + this.name + "'";
}
}
```
**LazySingletonAspectInstanceFactoryDecorator**
`LazySingletonAspectInstanceFactoryDecorator`类是一个装饰器,用于确保一个 `MetadataAwareAspectInstanceFactory` 只实例化一次。它包装了另一个 `MetadataAwareAspectInstanceFactory` 实例,并在首次调用 `getAspectInstance()` 方法时进行实例化。在后续的调用中,它将返回已经实例化的对象,而不会再次实例化。
```java
/**
* 修饰器,使 {@link MetadataAwareAspectInstanceFactory} 仅实例化一次。
*
* 作者:Rod Johnson, Juergen Hoeller
* @since 2.0
*/
@SuppressWarnings("serial")
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory, Serializable {
private final MetadataAwareAspectInstanceFactory maaif; // 要装饰的 MetadataAwareAspectInstanceFactory 实例
@Nullable
private volatile Object materialized; // 实例化的对象
/**
* 创建一个对给定 AspectInstanceFactory 进行懒初始化的修饰器。
* @param maaif 要装饰的 MetadataAwareAspectInstanceFactory
*/
public LazySingletonAspectInstanceFactoryDecorator(MetadataAwareAspectInstanceFactory maaif) {
Assert.notNull(maaif, "AspectInstanceFactory must not be null");
this.maaif = maaif;
}
/**
* 获取切面实例。
* 如果实例化过程中已经存在一个实例,则直接返回该实例;
* 否则,根据实例化互斥锁(如果存在)保证多线程环境下只实例化一次。
* 如果没有互斥锁,则直接实例化切面对象并将其赋值给 materialized 变量,然后返回该实例。
* 如果存在互斥锁,则使用该锁来保护实例化过程,确保在多线程环境下只有一个线程可以执行实例化操作。
*
* @return 切面实例
*/
@Override
public Object getAspectInstance() {
// 尝试获取已实例化的对象
Object aspectInstance = this.materialized;
// 如果不存在已实例化的对象
if (aspectInstance == null) {
// 获取实例化互斥锁
Object mutex = this.maaif.getAspectCreationMutex();
// 如果不存在互斥锁
if (mutex == null) {
// 直接实例化切面对象
aspectInstance = this.maaif.getAspectInstance();
// 将实例化后的对象赋值给 materialized 变量
this.materialized = aspectInstance;
} else {
// 使用互斥锁保护实例化过程
synchronized (mutex) {
// 再次尝试获取已实例化的对象
aspectInstance = this.materialized;
// 双重检查,确保在锁内部只实例化一次
if (aspectInstance == null) {
// 实例化切面对象
aspectInstance = this.maaif.getAspectInstance();
// 将实例化后的对象赋值给 materialized 变量
this.materialized = aspectInstance;
}
}
}
}
return aspectInstance; // 返回切面实例
}
/**
* 返回是否已经实例化。
*/
public boolean isMaterialized() {
return (this.materialized != null);
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return this.maaif.getAspectClassLoader();
}
@Override
public AspectMetadata getAspectMetadata() {
return this.maaif.getAspectMetadata();
}
@Override
@Nullable
public Object getAspectCreationMutex() {
return this.maaif.getAspectCreationMutex();
}
@Override
public int getOrder() {
return this.maaif.getOrder();
}
@Override
public String toString() {
return "LazySingletonAspectInstanceFactoryDecorator: decorating " + this.maaif;
}
}
```