EnableAspectJAutoProxy优化
parent
7164746998
commit
99249afe35
13
README.md
13
README.md
|
@ -217,16 +217,21 @@
|
||||||
- [AdvisorAdapterRegistry](spring-aop/spring-aop-advisorAdapterRegistry/README.md):适配各种Advice到AOP拦截器,注册和管理Advisor适配器。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [AdvisorAdapterRegistry](spring-aop/spring-aop-advisorAdapterRegistry/README.md):适配各种Advice到AOP拦截器,注册和管理Advisor适配器。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [AdvisorAdapter](spring-aop/spring-aop-advisorAdapter/README.md):适配不同类型通知到拦截器链。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [AdvisorAdapter](spring-aop/spring-aop-advisorAdapter/README.md):适配不同类型通知到拦截器链。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [ProxyMethodInvocation](spring-aop/spring-aop-proxyMethodInvocation/README.md):AOP方法调用代理,处理拦截器链和方法调用。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [ProxyMethodInvocation](spring-aop/spring-aop-proxyMethodInvocation/README.md):AOP方法调用代理,处理拦截器链和方法调用。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
|
- [@EnableAspectJAutoProxy](spring-aop/spring-aop-enableAspectJAutoProxy/README.md)
|
||||||
|
:启用AspectJ切面自动代理。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
|
- [AnnotationAwareAspectJAutoProxyCreator](spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md)
|
||||||
|
:创建AOP代理以应用AspectJ风格的切面。<img src="https://img.shields.io/badge/Level-%E5%9B%B0%E9%9A%BE-%23FF3030"></img>
|
||||||
|
- [BeanFactoryAspectJAdvisorsBuilder](spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md)
|
||||||
|
:构建@AspectJ注解切面,生成Spring AOP
|
||||||
|
Advisors。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
|
- [BeanFactoryAdvisorRetrievalHelper](spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md):帮助检索并管理
|
||||||
|
Spring AOP 中的 Advisor Beans。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [TargetSource](spring-aop/spring-aop-targetSource/README.md):管理AOP代理对象的获取与释放。<img src="https://img.shields.io/badge/Level-%E7%AE%80%E5%8D%95-0099ff"></img>
|
- [TargetSource](spring-aop/spring-aop-targetSource/README.md):管理AOP代理对象的获取与释放。<img src="https://img.shields.io/badge/Level-%E7%AE%80%E5%8D%95-0099ff"></img>
|
||||||
- [TargetSourceCreator](spring-aop/spring-aop-targetSourceCreator/README.md):创建特殊的目标源,定制代理对象的创建和管理。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [TargetSourceCreator](spring-aop/spring-aop-targetSourceCreator/README.md):创建特殊的目标源,定制代理对象的创建和管理。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [@EnableAspectJAutoProxy](spring-aop/spring-aop-enableAspectJAutoProxy/README.md):启用AspectJ切面自动代理。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
|
||||||
- [@EnableLoadTimeWeaving](spring-aop/spring-aop-enableLoadTimeWeaving/README.md):启用Spring加载时编织。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [@EnableLoadTimeWeaving](spring-aop/spring-aop-enableLoadTimeWeaving/README.md):启用Spring加载时编织。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [AspectInstanceFactory](spring-aop/spring-aop-aspectInstanceFactory/README.md):创建切面实例,支持多种实现方式。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [AspectInstanceFactory](spring-aop/spring-aop-aspectInstanceFactory/README.md):创建切面实例,支持多种实现方式。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [MetadataAwareAspectInstanceFactory](spring-aop/spring-aop-metadataAwareAspectInstanceFactory/README.md):管理切面实例和元数据,支持多种实例化策略。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [MetadataAwareAspectInstanceFactory](spring-aop/spring-aop-metadataAwareAspectInstanceFactory/README.md):管理切面实例和元数据,支持多种实例化策略。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [AspectJAdvisorFactory](spring-aop/spring-aop-aspectJAdvisorFactory/README.md):创建AspectJ通知器实例,管理切面通知的创建和配置。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
- [AspectJAdvisorFactory](spring-aop/spring-aop-aspectJAdvisorFactory/README.md):创建AspectJ通知器实例,管理切面通知的创建和配置。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
||||||
- [BeanFactoryAspectJAdvisorsBuilder](spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md):构建@AspectJ注解切面,生成Spring AOP Advisors。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
|
||||||
- [BeanFactoryAdvisorRetrievalHelper](spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md):帮助检索并管理 Spring AOP 中的 Advisor Beans。<img src="https://img.shields.io/badge/Level-%E4%B8%80%E8%88%AC-%23FF6347"></img>
|
|
||||||
- [AnnotationAwareAspectJAutoProxyCreator](spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md):创建AOP代理以应用AspectJ风格的切面。<img src="https://img.shields.io/badge/Level-%E5%9B%B0%E9%9A%BE-%23FF3030"></img>
|
|
||||||
- [AopContext](spring-aop/spring-aop-aopContext/README.md):获取Spring AOP代理对象的工具。<img src="https://img.shields.io/badge/Level-%E7%AE%80%E5%8D%95-0099ff"></img>
|
- [AopContext](spring-aop/spring-aop-aopContext/README.md):获取Spring AOP代理对象的工具。<img src="https://img.shields.io/badge/Level-%E7%AE%80%E5%8D%95-0099ff"></img>
|
||||||
- [ExposeInvocationInterceptor](spring-aop/spring-aop-exposeInvocationInterceptor/README.md):暴露Spring AOP方法调用上下文的拦截器。<img src="https://img.shields.io/badge/Level-%E7%AE%80%E5%8D%95-0099ff"></img>
|
- [ExposeInvocationInterceptor](spring-aop/spring-aop-exposeInvocationInterceptor/README.md):暴露Spring AOP方法调用上下文的拦截器。<img src="https://img.shields.io/badge/Level-%E7%AE%80%E5%8D%95-0099ff"></img>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
## AnnotationAwareAspectJAutoProxyCreator
|
## AnnotationAwareAspectJAutoProxyCreator
|
||||||
|
|
||||||
- [AnnotationAwareAspectJAutoProxyCreator](#annotationawareaspectjautoproxycreator)
|
- [AnnotationAwareAspectJAutoProxyCreator](#annotationawareaspectjautoproxycreator)
|
||||||
- [一、基本信息](#一基本信息)
|
- [一、基本信息](#一基本信息)
|
||||||
- [二、基本描述](#二基本描述)
|
- [二、基本描述](#二基本描述)
|
||||||
|
@ -7,7 +8,6 @@
|
||||||
- [五、最佳实践](#五最佳实践)
|
- [五、最佳实践](#五最佳实践)
|
||||||
- [六、时序图](#六时序图)
|
- [六、时序图](#六时序图)
|
||||||
- [七、源码分析](#七源码分析)
|
- [七、源码分析](#七源码分析)
|
||||||
- [八、常见问题](#八常见问题)
|
|
||||||
|
|
||||||
### 一、基本信息
|
### 一、基本信息
|
||||||
|
|
||||||
|
@ -71,17 +71,9 @@ class BeanPostProcessor {
|
||||||
class InstantiationAwareBeanPostProcessor {
|
class InstantiationAwareBeanPostProcessor {
|
||||||
<<Interface>>
|
<<Interface>>
|
||||||
|
|
||||||
}
|
|
||||||
class Ordered {
|
|
||||||
<<Interface>>
|
|
||||||
|
|
||||||
}
|
}
|
||||||
class ProxyConfig
|
class ProxyConfig
|
||||||
class ProxyProcessorSupport
|
class ProxyProcessorSupport
|
||||||
class Serializable {
|
|
||||||
<<Interface>>
|
|
||||||
|
|
||||||
}
|
|
||||||
class SmartInstantiationAwareBeanPostProcessor {
|
class SmartInstantiationAwareBeanPostProcessor {
|
||||||
<<Interface>>
|
<<Interface>>
|
||||||
|
|
||||||
|
@ -96,45 +88,81 @@ AspectJAwareAdvisorAutoProxyCreator --> AbstractAdvisorAutoProxyCreator
|
||||||
BeanClassLoaderAware --> Aware
|
BeanClassLoaderAware --> Aware
|
||||||
BeanFactoryAware --> Aware
|
BeanFactoryAware --> Aware
|
||||||
InstantiationAwareBeanPostProcessor --> BeanPostProcessor
|
InstantiationAwareBeanPostProcessor --> BeanPostProcessor
|
||||||
ProxyConfig ..> Serializable
|
|
||||||
ProxyProcessorSupport ..> AopInfrastructureBean
|
ProxyProcessorSupport ..> AopInfrastructureBean
|
||||||
ProxyProcessorSupport ..> BeanClassLoaderAware
|
ProxyProcessorSupport ..> BeanClassLoaderAware
|
||||||
ProxyProcessorSupport ..> Ordered
|
|
||||||
ProxyProcessorSupport --> ProxyConfig
|
ProxyProcessorSupport --> ProxyConfig
|
||||||
SmartInstantiationAwareBeanPostProcessor --> InstantiationAwareBeanPostProcessor
|
SmartInstantiationAwareBeanPostProcessor --> InstantiationAwareBeanPostProcessor
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
### 五、最佳实践
|
### 五、最佳实践
|
||||||
|
|
||||||
`AnnotationAwareAspectJAutoProxyCreator`类以及注解驱动的切面编程。通过注册`AnnotationAwareAspectJAutoProxyCreator`作为Bean,并指定应用程序配置类,Spring容器能够自动创建切面代理,并在运行时织入切面逻辑。最后,从容器中获取`MyService` bean并调用其方法,实现了面向切面编程的横切关注点的功能。
|
使用`EnableAspectJAutoProxy`
|
||||||
|
注解和Spring的基于注解的应用上下文来启用AspectJ自动代理功能。在程序中,首先创建了一个基于注解的应用上下文,然后通过该上下文获取了`MyService`
|
||||||
|
bean,并调用了其方法。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class AnnotationAwareAspectJAutoProxyCreatorDemo {
|
public class EnableAspectJAutoProxyDemo {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 创建一个默认的 Bean 工厂
|
// 创建基于注解的应用上下文
|
||||||
AnnotationConfigApplicationContext beanFactory = new AnnotationConfigApplicationContext();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
|
||||||
// 注册AnnotationAwareAspectJAutoProxyCreator作为Bean,用于自动创建切面代理
|
// 从应用上下文中获取MyService bean
|
||||||
beanFactory.registerBeanDefinition("internalAutoProxyCreator", new RootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class));
|
MyService myService = context.getBean(MyService.class);
|
||||||
// 注册应用程序配置类
|
|
||||||
beanFactory.register(AppConfig.class);
|
|
||||||
// 刷新应用程序上下文
|
|
||||||
beanFactory.refresh();
|
|
||||||
|
|
||||||
// 从容器中获取MyService bean
|
|
||||||
MyService myService = beanFactory.getBean(MyService.class);
|
|
||||||
// 调用MyService的方法
|
// 调用MyService的方法
|
||||||
myService.doSomething();
|
myService.foo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
运行结果,执行`MyService`中的`doSomething()`方法之前和之后,切面逻辑已成功织入。
|
`AppConfig` 类是一个使用 `@Configuration` 注解标记的配置类,通过 `@EnableAspectJAutoProxy` 开启了 AspectJ
|
||||||
|
自动代理功能,并通过 `@ComponentScan` 启用了组件扫描,用于自动发现和注册 Spring 组件。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Before executing the method...
|
|
||||||
Doing something...
|
@Configuration
|
||||||
After executing the method...
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`MyService` 类是一个使用 `@Service` 注解标记的服务类,提供了一个名为 `foo()` 的方法,该方法在调用时会打印消息 "foo..."。
|
||||||
|
|
||||||
|
```java
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MyService {
|
||||||
|
|
||||||
|
public void foo() {
|
||||||
|
System.out.println("foo...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`MyAspect`是一个使用了`@Aspect`注解的Java类,表示它是一个切面。在这个类中,定义了一个名为`advice`的方法,并使用了`@Before`
|
||||||
|
注解来指定在目标方法执行之前执行的通知。
|
||||||
|
|
||||||
|
```java
|
||||||
|
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class MyAspect {
|
||||||
|
|
||||||
|
@Before("execution(* com.xcs.spring.MyService+.*(..))")
|
||||||
|
public void before() {
|
||||||
|
System.out.println("Before method execution");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
运行结果,调用 `MyService` 类的 `foo()` 方法之前,成功地执行了一个切面通知,输出了 "Before method execution"
|
||||||
|
的消息,然后执行了 `foo()` 方法,输出了 "foo..." 的消息。
|
||||||
|
|
||||||
|
```java
|
||||||
|
Before method
|
||||||
|
execution
|
||||||
|
foo...
|
||||||
```
|
```
|
||||||
|
|
||||||
### 六、时序图
|
### 六、时序图
|
||||||
|
@ -569,18 +597,3 @@ protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
|
||||||
return proxyFactory.getProxy(classLoader);
|
return proxyFactory.getProxy(classLoader);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 八、常见问题
|
|
||||||
|
|
||||||
1. **无法注入依赖**
|
|
||||||
|
|
||||||
+ 可能会遇到无法注入依赖的问题,这通常是由于AOP代理的顺序问题导致的。
|
|
||||||
|
|
||||||
2. **切面未生效**
|
|
||||||
|
|
||||||
+ 有时配置了切面,但是切面并没有生效,可能是由于切面表达式不正确,或者AOP代理配置错误导致的。
|
|
||||||
|
|
||||||
|
|
||||||
4. **Bean未被代理**
|
|
||||||
|
|
||||||
+ 有时候配置了AnnotationAwareAspectJAutoProxyCreator,但是某些Bean并没有被代理,可能是由于Bean的作用域、类型或其他条件不满足自动代理的条件。
|
|
|
@ -1,24 +1,15 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
|
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
|
||||||
public class AnnotationAwareAspectJAutoProxyCreatorDemo {
|
public class AnnotationAwareAspectJAutoProxyCreatorDemo {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 创建一个默认的 Bean 工厂
|
// 创建基于注解的应用上下文
|
||||||
AnnotationConfigApplicationContext beanFactory = new AnnotationConfigApplicationContext();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
|
||||||
// 注册AnnotationAwareAspectJAutoProxyCreator作为Bean,用于自动创建切面代理
|
// 从应用上下文中获取MyService bean
|
||||||
beanFactory.registerBeanDefinition("internalAutoProxyCreator", new RootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class));
|
MyService myService = context.getBean(MyService.class);
|
||||||
// 注册应用程序配置类
|
|
||||||
beanFactory.register(AppConfig.class);
|
|
||||||
// 刷新应用程序上下文
|
|
||||||
beanFactory.refresh();
|
|
||||||
|
|
||||||
// 从容器中获取MyService bean
|
|
||||||
MyService myService = beanFactory.getBean(MyService.class);
|
|
||||||
// 调用MyService的方法
|
// 调用MyService的方法
|
||||||
myService.doSomething();
|
myService.foo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,11 @@ package com.xcs.spring;
|
||||||
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ComponentScan("com.xcs.spring")
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
public class AppConfig {
|
public class AppConfig {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,15 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
import org.aspectj.lang.annotation.After;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Before;
|
import org.aspectj.lang.annotation.Before;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Aspect
|
@Aspect
|
||||||
@Component
|
@Component
|
||||||
class MyAspect {
|
public class MyAspect {
|
||||||
|
|
||||||
@Before("execution(* com.xcs.spring.MyService.doSomething(..))")
|
@Before("execution(* com.xcs.spring.MyService+.*(..))")
|
||||||
public void before() {
|
public void before() {
|
||||||
System.out.println("Before executing the method..." );
|
System.out.println("Before method execution");
|
||||||
}
|
|
||||||
|
|
||||||
@After("execution(* com.xcs.spring.MyService.doSomething(..))")
|
|
||||||
public void after() {
|
|
||||||
System.out.println("After executing the method..." );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class MyService {
|
public class MyService {
|
||||||
public void doSomething() {
|
|
||||||
System.out.println("Doing something...");
|
public void foo() {
|
||||||
|
System.out.println("foo...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
- [二、基本描述](#二基本描述)
|
- [二、基本描述](#二基本描述)
|
||||||
- [三、主要功能](#三主要功能)
|
- [三、主要功能](#三主要功能)
|
||||||
- [四、最佳实践](#四最佳实践)
|
- [四、最佳实践](#四最佳实践)
|
||||||
- [五、源码分析](#五源码分析)
|
- [五、时序图](#五时序图)
|
||||||
- [六、常见问题](#六常见问题)
|
- [六、源码分析](#六源码分析)
|
||||||
|
|
||||||
### 一、基本信息
|
### 一、基本信息
|
||||||
|
|
||||||
|
@ -33,30 +33,44 @@
|
||||||
|
|
||||||
### 四、最佳实践
|
### 四、最佳实践
|
||||||
|
|
||||||
使用 `BeanFactoryAdvisorRetrievalHelper` 类来从一个默认的 Bean 工厂中检索 Advisor,并打印出这些 Advisor 的列表。首先,我们创建一个默认的 Bean 工厂,并向其注册一个名为 "myAdvisor" 的 Advisor。然后,我们创建了 `BeanFactoryAdvisorRetrievalHelper` 实例,并将 Bean 工厂传入其中。接着,通过调用 `findAdvisorBeans()` 方法,我们获取了 Bean 工厂中的 Advisor 列表,并通过循环遍历的方式打印出每个 Advisor 的信息。
|
使用基于注解的应用上下文来获取并调用 `MyService` Bean 的 `foo()`
|
||||||
|
方法。首先,创建了一个 `AnnotationConfigApplicationContext` 实例,通过传入 `AppConfig.class`
|
||||||
|
来初始化基于注解的应用上下文。然后,通过 `context.getBean(MyService.class)` 获取了 `MyService` Bean
|
||||||
|
的实例,并调用了其 `foo()` 方法。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class BeanFactoryAdvisorRetrievalHelperDemo {
|
public class BeanFactoryAdvisorRetrievalHelperDemo {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 创建一个默认的 Bean 工厂
|
// 创建基于注解的应用上下文
|
||||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
|
||||||
// 向 Bean 工厂注册一个名为 "myAdvisor" 的 Advisor
|
// 从应用上下文中获取MyService bean
|
||||||
beanFactory.registerSingleton("myAdvisor", new MyAdvisor());
|
MyService myService = context.getBean(MyService.class);
|
||||||
|
// 调用MyService的方法
|
||||||
// 创建 BeanFactoryAdvisorRetrievalHelper 实例,并传入 Bean 工厂
|
myService.foo();
|
||||||
BeanFactoryAdvisorRetrievalHelper helper = new BeanFactoryAdvisorRetrievalHelper(beanFactory);
|
|
||||||
// 获取 Bean 工厂中的 Advisor 列表
|
|
||||||
List<Advisor> advisors = helper.findAdvisorBeans();
|
|
||||||
// 打印 Advisors
|
|
||||||
advisors.forEach(System.out::println);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`MyAdvisor` 类是一个自定义的 Advisor,继承自 `AbstractPointcutAdvisor`,用于定义切面的逻辑。在该类中,`getPointcut()` 方法返回一个始终为真的 Pointcut,表示适用于所有的连接点;`getAdvice()` 方法返回一个空的 Advice,表示不对目标方法添加任何额外的通知逻辑。因此,该 Advisor 没有实际的业务逻辑,仅作为演示目的。
|
`AppConfig` 类是一个使用 `@Configuration` 注解标记的配置类,通过 `@EnableAspectJAutoProxy` 开启了 AspectJ
|
||||||
|
自动代理功能,并通过 `@ComponentScan` 启用了组件扫描,用于自动发现和注册 Spring 组件。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
使用 `@Component` 注解标记的自定义 Advisor,继承自 `AbstractPointcutAdvisor`。它定义了一个总是返回真值的 Pointcut,并将一个自定义的
|
||||||
|
Advice `MyAdvice` 应用于目标方法上。
|
||||||
|
|
||||||
|
```java
|
||||||
|
|
||||||
|
@Component
|
||||||
public class MyAdvisor extends AbstractPointcutAdvisor {
|
public class MyAdvisor extends AbstractPointcutAdvisor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,18 +80,67 @@ public class MyAdvisor extends AbstractPointcutAdvisor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Advice getAdvice() {
|
public Advice getAdvice() {
|
||||||
return Advisor.EMPTY_ADVICE;
|
return new MyAdvice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
运行结果,成功地从 Bean 工厂中获取了Advisor。
|
`MyAdvice` 类是一个实现了 `MethodBeforeAdvice` 接口的自定义通知类,用于在目标方法执行前执行特定逻辑。在 `before()`
|
||||||
|
方法中,它打印了一条消息:"Before method execution"。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
com.xcs.spring.MyAdvisor@1f7030a6
|
public class MyAdvice implements MethodBeforeAdvice {
|
||||||
|
@Override
|
||||||
|
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||||
|
System.out.println("Before method execution");
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 五、源码分析
|
`MyService` 类是一个使用 `@Service` 注解标记的服务类,提供了一个名为 `foo()` 的方法,该方法在调用时会打印消息 "foo..."。
|
||||||
|
|
||||||
|
```java
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MyService {
|
||||||
|
|
||||||
|
public void foo() {
|
||||||
|
System.out.println("foo...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
运行结果,调用 `MyService` 类的 `foo()` 方法之前,成功地执行了一个切面通知,输出了 "Before method execution"
|
||||||
|
的消息,然后执行了 `foo()` 方法,输出了 "foo..." 的消息。
|
||||||
|
|
||||||
|
```java
|
||||||
|
Before method
|
||||||
|
execution
|
||||||
|
foo...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 五、时序图
|
||||||
|
|
||||||
|
~~~mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
AbstractAutowireCapableBeanFactory->>AbstractAutoProxyCreator: postProcessAfterInitialization()
|
||||||
|
Note over AbstractAutowireCapableBeanFactory,AbstractAutoProxyCreator: 调用后处理方法
|
||||||
|
AbstractAutoProxyCreator->>AbstractAutoProxyCreator: wrapIfNecessary()
|
||||||
|
Note over AbstractAutoProxyCreator: 调用包装方法
|
||||||
|
AbstractAutoProxyCreator->>AbstractAdvisorAutoProxyCreator: getAdvicesAndAdvisorsForBean()
|
||||||
|
Note over AbstractAutoProxyCreator,AbstractAdvisorAutoProxyCreator: 获取通知和 Advisors
|
||||||
|
AbstractAdvisorAutoProxyCreator->>AbstractAdvisorAutoProxyCreator: findEligibleAdvisors()
|
||||||
|
Note over AbstractAdvisorAutoProxyCreator: 查找合适的 Advisors
|
||||||
|
AbstractAdvisorAutoProxyCreator->>AnnotationAwareAspectJAutoProxyCreator: findCandidateAdvisors()
|
||||||
|
Note over AbstractAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator: 查找候选的 Advisors
|
||||||
|
AnnotationAwareAspectJAutoProxyCreator->>AbstractAdvisorAutoProxyCreator: super.findCandidateAdvisors()
|
||||||
|
Note over AnnotationAwareAspectJAutoProxyCreator,AbstractAdvisorAutoProxyCreator: 调用父类的查找候选的 Advisors
|
||||||
|
AbstractAdvisorAutoProxyCreator->>BeanFactoryAdvisorRetrievalHelper: findAdvisorBeans()
|
||||||
|
Note over AbstractAdvisorAutoProxyCreator,BeanFactoryAdvisorRetrievalHelper: 查找当前Bean工厂中所有符合条件的Advisor
|
||||||
|
BeanFactoryAdvisorRetrievalHelper->>AbstractAutoProxyCreator: 返回 advisors
|
||||||
|
~~~
|
||||||
|
|
||||||
|
### 六、源码分析
|
||||||
|
|
||||||
在`org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans`方法中,主要功能是在当前的 Bean 工厂中查找所有符合条件的 Advisor Beans。它忽略了 FactoryBeans,并排除了当前正在创建中的 Beans。该方法首先确定 Advisor Bean 的名称列表,如果尚未缓存,则通过 `BeanFactoryUtils.beanNamesForTypeIncludingAncestors()` 方法获取。然后,它遍历这些 Advisor Bean 的名称,检查它们是否符合条件,并将符合条件的 Advisor Bean 添加到结果列表中。在添加之前,它会检查该 Bean 是否当前正在创建中,如果是,则跳过。最后,返回包含所有符合条件的 Advisor Beans 的列表。
|
在`org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans`方法中,主要功能是在当前的 Bean 工厂中查找所有符合条件的 Advisor Beans。它忽略了 FactoryBeans,并排除了当前正在创建中的 Beans。该方法首先确定 Advisor Bean 的名称列表,如果尚未缓存,则通过 `BeanFactoryUtils.beanNamesForTypeIncludingAncestors()` 方法获取。然后,它遍历这些 Advisor Bean 的名称,检查它们是否符合条件,并将符合条件的 Advisor Bean 添加到结果列表中。在添加之前,它会检查该 Bean 是否当前正在创建中,如果是,则跳过。最后,返回包含所有符合条件的 Advisor Beans 的列表。
|
||||||
|
|
||||||
|
@ -142,21 +205,3 @@ public List<Advisor> findAdvisorBeans() {
|
||||||
return advisors;
|
return advisors;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 六、常见问题
|
|
||||||
|
|
||||||
1. **忽略FactoryBeans**
|
|
||||||
|
|
||||||
+ 在 `findAdvisorBeans()` 方法中,该类会忽略 FactoryBeans,只处理常规的 Advisor Beans。这是因为 FactoryBeans 可能会在初始化时产生副作用,而 `BeanFactoryAdvisorRetrievalHelper` 需要保持所有常规 Beans 未初始化,以便自动代理创建器能够正确地应用于它们。
|
|
||||||
|
|
||||||
2. **排除当前正在创建的Beans**
|
|
||||||
|
|
||||||
+ 在遍历 Advisor Beans 名称列表时,`findAdvisorBeans()` 方法会排除当前正在创建中的 Beans。这是为了避免在 Bean 的创建过程中引入不稳定的代理逻辑。
|
|
||||||
|
|
||||||
3. **错误处理**
|
|
||||||
|
|
||||||
+ 当尝试获取 Advisor Bean 时,可能会抛出 `BeanCreationException` 异常。`BeanFactoryAdvisorRetrievalHelper` 需要正确处理这些异常情况,例如,当 Advisor Bean 的依赖 Bean 正在创建中时,可以选择跳过该 Advisor。
|
|
||||||
|
|
||||||
4. **缓存机制**
|
|
||||||
|
|
||||||
+ 为了提高性能,`BeanFactoryAdvisorRetrievalHelper` 类使用了缓存机制来存储 Advisor Bean 的名称列表。需要注意,在 Bean 工厂中添加或删除 Advisor Bean 时,需要更新缓存以确保数据的一致性。
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.xcs.spring;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
}
|
|
@ -1,24 +1,15 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
import org.springframework.aop.Advisor;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper;
|
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class BeanFactoryAdvisorRetrievalHelperDemo {
|
public class BeanFactoryAdvisorRetrievalHelperDemo {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 创建一个默认的 Bean 工厂
|
// 创建基于注解的应用上下文
|
||||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
|
||||||
// 向 Bean 工厂注册一个名为 "myAspect" 的 Advisor
|
// 从应用上下文中获取MyService bean
|
||||||
beanFactory.registerSingleton("myAspect", new MyAdvisor());
|
MyService myService = context.getBean(MyService.class);
|
||||||
|
// 调用MyService的方法
|
||||||
// 创建 BeanFactoryAdvisorRetrievalHelper 实例,并传入 Bean 工厂
|
myService.foo();
|
||||||
BeanFactoryAdvisorRetrievalHelper helper = new BeanFactoryAdvisorRetrievalHelper(beanFactory);
|
|
||||||
// 获取 Bean 工厂中的 Advisor 列表
|
|
||||||
List<Advisor> advisors = helper.findAdvisorBeans();
|
|
||||||
// 打印 Advisors
|
|
||||||
advisors.forEach(System.out::println);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.xcs.spring;
|
||||||
|
|
||||||
|
import org.springframework.aop.MethodBeforeAdvice;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class MyAdvice implements MethodBeforeAdvice {
|
||||||
|
@Override
|
||||||
|
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||||
|
System.out.println("Before method execution");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
import org.aopalliance.aop.Advice;
|
import org.aopalliance.aop.Advice;
|
||||||
import org.springframework.aop.Advisor;
|
|
||||||
import org.springframework.aop.Pointcut;
|
import org.springframework.aop.Pointcut;
|
||||||
import org.springframework.aop.support.AbstractPointcutAdvisor;
|
import org.springframework.aop.support.AbstractPointcutAdvisor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
public class MyAdvisor extends AbstractPointcutAdvisor {
|
public class MyAdvisor extends AbstractPointcutAdvisor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -14,6 +15,6 @@ public class MyAdvisor extends AbstractPointcutAdvisor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Advice getAdvice() {
|
public Advice getAdvice() {
|
||||||
return Advisor.EMPTY_ADVICE;
|
return new MyAdvice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.xcs.spring;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MyService {
|
||||||
|
|
||||||
|
public void foo() {
|
||||||
|
System.out.println("foo...");
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,8 +5,8 @@
|
||||||
- [二、基本描述](#二基本描述)
|
- [二、基本描述](#二基本描述)
|
||||||
- [三、主要功能](#三主要功能)
|
- [三、主要功能](#三主要功能)
|
||||||
- [四、最佳实践](#四最佳实践)
|
- [四、最佳实践](#四最佳实践)
|
||||||
- [五、源码分析](#五源码分析)
|
- [五、时序图](#五时序图)
|
||||||
- [六、常见问题](#六常见问题)
|
- [六、源码分析](#六源码分析)
|
||||||
|
|
||||||
### 一、基本信息
|
### 一、基本信息
|
||||||
|
|
||||||
|
@ -36,63 +36,95 @@
|
||||||
|
|
||||||
### 四、最佳实践
|
### 四、最佳实践
|
||||||
|
|
||||||
使用 `BeanFactoryAspectJAdvisorsBuilder` 类来构建基于 AspectJ 注解的切面,首先创建了一个默认的 Bean 工厂,并注册了一个名为 "myAspect" 的单例 Bean,然后通过 `BeanFactoryAspectJAdvisorsBuilder` 实例构建了 AspectJ Advisors,并将其打印出来。
|
使用基于注解的应用上下文来获取并调用 `MyService` Bean 的 `foo()`
|
||||||
|
方法。首先,创建了一个 `AnnotationConfigApplicationContext` 实例,通过传入 `AppConfig.class`
|
||||||
|
来初始化基于注解的应用上下文。然后,通过 `context.getBean(MyService.class)` 获取了 `MyService` Bean
|
||||||
|
的实例,并调用了其 `foo()` 方法。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class BeanFactoryAspectJAdvisorsBuilderDemo {
|
public class BeanFactoryAspectJAdvisorsBuilderDemo {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 创建一个默认的 Bean 工厂
|
// 创建基于注解的应用上下文
|
||||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
|
||||||
// 在 Bean 工厂中注册一个名为 "myAspect" 的单例 Bean,类型为 MyAspect
|
// 从应用上下文中获取MyService bean
|
||||||
beanFactory.registerSingleton("myAspect", new MyAspect());
|
MyService myService = context.getBean(MyService.class);
|
||||||
|
// 调用MyService的方法
|
||||||
// 创建 BeanFactoryAspectJAdvisorsBuilder 实例,并传入 Bean 工厂和 ReflectiveAspectJAdvisorFactory 实例
|
myService.foo();
|
||||||
BeanFactoryAspectJAdvisorsBuilder builder = new BeanFactoryAspectJAdvisorsBuilder(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
|
|
||||||
// 构建 AspectJ Advisors
|
|
||||||
List<Advisor> advisors = builder.buildAspectJAdvisors();
|
|
||||||
// 打印 Advisors
|
|
||||||
advisors.forEach(System.out::println);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
使用了 AspectJ 的注解 `@Aspect` 进行标记。在该切面类中,包含了两个通知方法`before()` 和 `after()`,分别使用 `@Before` 和 `@After` 注解标记。这两个通知方法分别在目标方法 `com.xcs.spring.MyService.doSomething()` 执行之前和之后执行,并输出相应的日志信息。
|
`AppConfig` 类是一个使用 `@Configuration` 注解标记的配置类,通过 `@EnableAspectJAutoProxy` 开启了 AspectJ
|
||||||
|
自动代理功能,并通过 `@ComponentScan` 启用了组件扫描,用于自动发现和注册 Spring 组件。
|
||||||
|
|
||||||
|
```java
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
通过 @Aspect 和 @Component 注解将其标记为 Spring 组件,并定义了一个在 com.xcs.spring.MyService 类的 foo
|
||||||
|
方法执行前执行的前置通知(Before advice)。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Aspect
|
@Aspect
|
||||||
|
@Component
|
||||||
class MyAspect {
|
class MyAspect {
|
||||||
|
|
||||||
@Before("execution(* com.xcs.spring.MyService.doSomething(..))")
|
@Before("execution(* com.xcs.spring.MyService.foo(..))")
|
||||||
public void before() {
|
public void before() {
|
||||||
System.out.println("Before executing the method..." );
|
System.out.println("Before method execution");
|
||||||
}
|
|
||||||
|
|
||||||
@After("execution(* com.xcs.spring.MyService.doSomething(..))")
|
|
||||||
public void after() {
|
|
||||||
System.out.println("After executing the method..." );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
定义了一个名为 `MyService` 的简单 Java 类,其中包含一个名为 `doSomething()` 的方法。该方法简单地打印一条日志信息 "Doing something..."。这个类作为示例类使用,用来演示在 AOP 中如何应用切面逻辑。
|
`MyService` 类是一个使用 `@Service` 注解标记的服务类,提供了一个名为 `foo()` 的方法,该方法在调用时会打印消息 "foo..."。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
|
@Service
|
||||||
public class MyService {
|
public class MyService {
|
||||||
public void doSomething() {
|
|
||||||
System.out.println("Doing something...");
|
public void foo() {
|
||||||
|
System.out.println("foo...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
运行结果,显示了两个 Advisor 对象的信息,它们分别对应着切面类 `MyAspect` 中的 `before()` 和 `after()` 方法,并针对相同的切点表达式 `execution(* com.xcs.spring.MyService.doSomething(..))`。
|
运行结果,调用 `MyService` 类的 `foo()` 方法之前,成功地执行了一个切面通知,输出了 "Before method execution"
|
||||||
|
的消息,然后执行了 `foo()` 方法,输出了 "foo..." 的消息。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
InstantiationModelAwarePointcutAdvisor: expression [execution(* com.xcs.spring.MyService.doSomething(..))]; advice method [public void com.xcs.spring.MyAspect.before()]; perClauseKind=SINGLETON
|
Before method
|
||||||
InstantiationModelAwarePointcutAdvisor: expression [execution(* com.xcs.spring.MyService.doSomething(..))]; advice method [public void com.xcs.spring.MyAspect.after()]; perClauseKind=SINGLETON
|
execution
|
||||||
|
foo...
|
||||||
```
|
```
|
||||||
|
|
||||||
### 五、源码分析
|
### 五、时序图
|
||||||
|
|
||||||
|
~~~mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
AbstractAutowireCapableBeanFactory->>AbstractAutoProxyCreator: postProcessAfterInitialization()
|
||||||
|
Note over AbstractAutowireCapableBeanFactory,AbstractAutoProxyCreator: 调用后处理方法
|
||||||
|
AbstractAutoProxyCreator->>AbstractAutoProxyCreator: wrapIfNecessary()
|
||||||
|
Note over AbstractAutoProxyCreator: 调用包装方法
|
||||||
|
AbstractAutoProxyCreator->>AbstractAdvisorAutoProxyCreator: getAdvicesAndAdvisorsForBean()
|
||||||
|
Note over AbstractAutoProxyCreator,AbstractAdvisorAutoProxyCreator: 获取通知和 Advisors
|
||||||
|
AbstractAdvisorAutoProxyCreator->>AbstractAdvisorAutoProxyCreator: findEligibleAdvisors()
|
||||||
|
Note over AbstractAdvisorAutoProxyCreator: 查找合适的 Advisors
|
||||||
|
AbstractAdvisorAutoProxyCreator->>AnnotationAwareAspectJAutoProxyCreator: findCandidateAdvisors()
|
||||||
|
Note over AbstractAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator: 查找候选的 Advisors
|
||||||
|
AnnotationAwareAspectJAutoProxyCreator->>BeanFactoryAspectJAdvisorsBuilder: buildAspectJAdvisors()
|
||||||
|
Note over AnnotationAwareAspectJAutoProxyCreator,BeanFactoryAspectJAdvisorsBuilder: 构建 AspectJ Advisors
|
||||||
|
BeanFactoryAspectJAdvisorsBuilder->>AbstractAutoProxyCreator: 返回 advisors
|
||||||
|
~~~
|
||||||
|
|
||||||
|
### 六、源码分析
|
||||||
|
|
||||||
在`org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors`方法中,主要负责在当前的 Bean 工厂中查找使用 AspectJ 注解标记的切面 Bean,并将其转换为 Spring AOP Advisors 的列表。它遍历所有的 Bean 名称,识别切面 Bean,并根据其实例化模型(单例或多例)创建对应的 AspectJ Advisors。在处理过程中,还会缓存单例切面的 Advisors,以提高性能。
|
在`org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors`方法中,主要负责在当前的 Bean 工厂中查找使用 AspectJ 注解标记的切面 Bean,并将其转换为 Spring AOP Advisors 的列表。它遍历所有的 Bean 名称,识别切面 Bean,并根据其实例化模型(单例或多例)创建对应的 AspectJ Advisors。在处理过程中,还会缓存单例切面的 Advisors,以提高性能。
|
||||||
|
|
||||||
|
@ -226,8 +258,5 @@ private boolean hasAspectAnnotation(Class<?> clazz) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 六、常见问题
|
|
||||||
|
|
||||||
1. **实例化模型匹配**
|
|
||||||
|
|
||||||
+ 在判断切面的实例化模型时,需要确保该模型与实际的 Bean 实例化策略相匹配。如果切面 Bean 被声明为单例模式,但实际上是多例的,或者反之,则可能会导致不一致或异常情况。
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.xcs.spring;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
}
|
|
@ -1,25 +1,15 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
import org.springframework.aop.Advisor;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder;
|
|
||||||
import org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory;
|
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class BeanFactoryAspectJAdvisorsBuilderDemo {
|
public class BeanFactoryAspectJAdvisorsBuilderDemo {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 创建一个默认的 Bean 工厂
|
// 创建基于注解的应用上下文
|
||||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
|
||||||
// 在 Bean 工厂中注册一个名为 "myAspect" 的单例 Bean,类型为 MyAspect
|
// 从应用上下文中获取MyService bean
|
||||||
beanFactory.registerSingleton("myAspect", new MyAspect());
|
MyService myService = context.getBean(MyService.class);
|
||||||
|
// 调用MyService的方法
|
||||||
// 创建 BeanFactoryAspectJAdvisorsBuilder 实例,并传入 Bean 工厂和 ReflectiveAspectJAdvisorFactory 实例
|
myService.foo();
|
||||||
BeanFactoryAspectJAdvisorsBuilder builder = new BeanFactoryAspectJAdvisorsBuilder(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
|
|
||||||
// 构建 AspectJ Advisors
|
|
||||||
List<Advisor> advisors = builder.buildAspectJAdvisors();
|
|
||||||
// 打印 Advisors
|
|
||||||
advisors.forEach(System.out::println);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
import org.aspectj.lang.annotation.After;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Before;
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Aspect
|
@Aspect
|
||||||
|
@Component
|
||||||
class MyAspect {
|
class MyAspect {
|
||||||
|
|
||||||
@Before("execution(* com.xcs.spring.MyService.doSomething(..))")
|
@Before("execution(* com.xcs.spring.MyService.foo(..))")
|
||||||
public void before() {
|
public void before() {
|
||||||
System.out.println("Before executing the method..." );
|
System.out.println("Before method execution");
|
||||||
}
|
|
||||||
|
|
||||||
@After("execution(* com.xcs.spring.MyService.doSomething(..))")
|
|
||||||
public void after() {
|
|
||||||
System.out.println("After executing the method..." );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
public class MyService {
|
public class MyService {
|
||||||
public void doSomething() {
|
public void foo() {
|
||||||
System.out.println("Doing something...");
|
System.out.println("foo...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
## @EnableAspectJAutoProxy
|
## @EnableAspectJAutoProxy
|
||||||
|
|
||||||
- [@EnableAspectJAutoProxy](#@EnableAspectJAutoProxy)
|
- [@EnableAspectJAutoProxy](#enableaspectjautoproxy)
|
||||||
- [一、基本信息](#一基本信息)
|
- [一、基本信息](#一基本信息)
|
||||||
- [二、基本描述](#二基本描述)
|
- [二、基本描述](#二基本描述)
|
||||||
- [三、主要功能](#三主要功能)
|
- [三、主要功能](#三主要功能)
|
||||||
- [四、注解源码](#注解源码)
|
- [四、注解源码](#四注解源码)
|
||||||
- [五、最佳实践](#五最佳实践)
|
- [五、最佳实践](#五最佳实践)
|
||||||
- [六、源码分析](#六源码分析)
|
- [六、源码分析](#六源码分析)
|
||||||
- [七、常见问题](#七常见问题)
|
|
||||||
|
|
||||||
### 一、基本信息
|
### 一、基本信息
|
||||||
|
|
||||||
|
@ -175,30 +175,23 @@ public class EnableAspectJAutoProxyDemo {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
通过`@Configuration`注解表示它是一个配置类,用于配置Spring应用的bean。其中,通过`@EnableAspectJAutoProxy`
|
`AppConfig` 类是一个使用 `@Configuration` 注解标记的配置类,通过 `@EnableAspectJAutoProxy` 开启了 AspectJ
|
||||||
注解启用了AspectJ自动代理功能,使得Spring能够自动处理切面。在配置中定义了两个bean:`MyService`和`MyAspect`
|
自动代理功能,并通过 `@ComponentScan` 启用了组件扫描,用于自动发现和注册 Spring 组件。
|
||||||
,分别用于创建`MyService`的实例和`MyAspect`切面的实例。
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAspectJAutoProxy
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
public class AppConfig {
|
public class AppConfig {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MyService myService() {
|
|
||||||
return new MyService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MyAspect myAspect() {
|
|
||||||
return new MyAspect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`FooService`是一个简单的Java类,其中包含了一个名为`foo`的方法。
|
`MyService` 类是一个使用 `@Service` 注解标记的服务类,提供了一个名为 `foo()` 的方法,该方法在调用时会打印消息 "foo..."。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
|
@Service
|
||||||
public class MyService {
|
public class MyService {
|
||||||
|
|
||||||
public void foo() {
|
public void foo() {
|
||||||
|
@ -211,6 +204,7 @@ public class MyService {
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Aspect
|
@Aspect
|
||||||
|
@Component
|
||||||
public class MyAspect {
|
public class MyAspect {
|
||||||
|
|
||||||
@Before("execution(* com.xcs.spring.MyService+.*(..))")
|
@Before("execution(* com.xcs.spring.MyService+.*(..))")
|
||||||
|
@ -220,6 +214,15 @@ public class MyAspect {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
运行结果,调用 `MyService` 类的 `foo()` 方法之前,成功地执行了一个切面通知,输出了 "Before method execution"
|
||||||
|
的消息,然后执行了 `foo()` 方法,输出了 "foo..." 的消息。
|
||||||
|
|
||||||
|
```java
|
||||||
|
Before method
|
||||||
|
execution
|
||||||
|
foo...
|
||||||
|
```
|
||||||
|
|
||||||
### 六、源码分析
|
### 六、源码分析
|
||||||
|
|
||||||
在`org.springframework.context.annotation.AspectJAutoProxyRegistrar#registerBeanDefinitions`方法中,首先注册了AspectJ注解自动代理创建器,然后获取了`@EnableAspectJAutoProxy`注解的属性。如果`@EnableAspectJAutoProxy`注解中指定了`proxyTargetClass`属性为true,则强制使用CGLIB代理;如果指定了`exposeProxy`属性为true,则强制代理对象暴露为ThreadLocal。
|
在`org.springframework.context.annotation.AspectJAutoProxyRegistrar#registerBeanDefinitions`方法中,首先注册了AspectJ注解自动代理创建器,然后获取了`@EnableAspectJAutoProxy`注解的属性。如果`@EnableAspectJAutoProxy`注解中指定了`proxyTargetClass`属性为true,则强制使用CGLIB代理;如果指定了`exposeProxy`属性为true,则强制代理对象暴露为ThreadLocal。
|
||||||
|
@ -260,6 +263,8 @@ public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessar
|
||||||
|
|
||||||
在`org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry,source)`方法中,注册AspectJ注解自动代理创建器,并且可以指定源对象。在方法中,它调用了一个辅助方法`registerOrEscalateApcAsRequired`,该方法会根据需要注册或升级AspectJ注解自动代理创建器,并返回相应的BeanDefinition。
|
在`org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry,source)`方法中,注册AspectJ注解自动代理创建器,并且可以指定源对象。在方法中,它调用了一个辅助方法`registerOrEscalateApcAsRequired`,该方法会根据需要注册或升级AspectJ注解自动代理创建器,并返回相应的BeanDefinition。
|
||||||
|
|
||||||
|
[AnnotationAwareAspectJAutoProxyCreator源码分析](../spring-aop-annotationAwareAspectJAutoProxyCreator/README.md)
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Nullable
|
@Nullable
|
||||||
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
|
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAspectJAutoProxy
|
@EnableAspectJAutoProxy
|
||||||
|
@ComponentScan
|
||||||
public class AppConfig {
|
public class AppConfig {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MyService myService() {
|
|
||||||
return new MyService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MyAspect myAspect() {
|
|
||||||
return new MyAspect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@ package com.xcs.spring;
|
||||||
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Before;
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Aspect
|
@Aspect
|
||||||
|
@Component
|
||||||
public class MyAspect {
|
public class MyAspect {
|
||||||
|
|
||||||
@Before("execution(* com.xcs.spring.MyService+.*(..))")
|
@Before("execution(* com.xcs.spring.MyService+.*(..))")
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package com.xcs.spring;
|
package com.xcs.spring;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
public class MyService {
|
public class MyService {
|
||||||
|
|
||||||
public void foo() {
|
public void foo() {
|
||||||
|
|
Loading…
Reference in New Issue