diff --git a/README.md b/README.md
index 28757ba..5a13204 100644
--- a/README.md
+++ b/README.md
@@ -217,16 +217,21 @@
- [AdvisorAdapterRegistry](spring-aop/spring-aop-advisorAdapterRegistry/README.md):适配各种Advice到AOP拦截器,注册和管理Advisor适配器。
- [AdvisorAdapter](spring-aop/spring-aop-advisorAdapter/README.md):适配不同类型通知到拦截器链。
- [ProxyMethodInvocation](spring-aop/spring-aop-proxyMethodInvocation/README.md):AOP方法调用代理,处理拦截器链和方法调用。
+ - [@EnableAspectJAutoProxy](spring-aop/spring-aop-enableAspectJAutoProxy/README.md)
+ :启用AspectJ切面自动代理。
+ - [AnnotationAwareAspectJAutoProxyCreator](spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md)
+ :创建AOP代理以应用AspectJ风格的切面。
+ - [BeanFactoryAspectJAdvisorsBuilder](spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md)
+ :构建@AspectJ注解切面,生成Spring AOP
+ Advisors。
+ - [BeanFactoryAdvisorRetrievalHelper](spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md):帮助检索并管理
+ Spring AOP 中的 Advisor Beans。
- [TargetSource](spring-aop/spring-aop-targetSource/README.md):管理AOP代理对象的获取与释放。
- [TargetSourceCreator](spring-aop/spring-aop-targetSourceCreator/README.md):创建特殊的目标源,定制代理对象的创建和管理。
- - [@EnableAspectJAutoProxy](spring-aop/spring-aop-enableAspectJAutoProxy/README.md):启用AspectJ切面自动代理。
- [@EnableLoadTimeWeaving](spring-aop/spring-aop-enableLoadTimeWeaving/README.md):启用Spring加载时编织。
- [AspectInstanceFactory](spring-aop/spring-aop-aspectInstanceFactory/README.md):创建切面实例,支持多种实现方式。
- [MetadataAwareAspectInstanceFactory](spring-aop/spring-aop-metadataAwareAspectInstanceFactory/README.md):管理切面实例和元数据,支持多种实例化策略。
- [AspectJAdvisorFactory](spring-aop/spring-aop-aspectJAdvisorFactory/README.md):创建AspectJ通知器实例,管理切面通知的创建和配置。
- - [BeanFactoryAspectJAdvisorsBuilder](spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md):构建@AspectJ注解切面,生成Spring AOP Advisors。
- - [BeanFactoryAdvisorRetrievalHelper](spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md):帮助检索并管理 Spring AOP 中的 Advisor Beans。
- - [AnnotationAwareAspectJAutoProxyCreator](spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md):创建AOP代理以应用AspectJ风格的切面。
- [AopContext](spring-aop/spring-aop-aopContext/README.md):获取Spring AOP代理对象的工具。
- [ExposeInvocationInterceptor](spring-aop/spring-aop-exposeInvocationInterceptor/README.md):暴露Spring AOP方法调用上下文的拦截器。
diff --git a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md
index 7b4f3f1..dcc4eba 100644
--- a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md
+++ b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md
@@ -1,4 +1,5 @@
## AnnotationAwareAspectJAutoProxyCreator
+
- [AnnotationAwareAspectJAutoProxyCreator](#annotationawareaspectjautoproxycreator)
- [一、基本信息](#一基本信息)
- [二、基本描述](#二基本描述)
@@ -7,7 +8,6 @@
- [五、最佳实践](#五最佳实践)
- [六、时序图](#六时序图)
- [七、源码分析](#七源码分析)
- - [八、常见问题](#八常见问题)
### 一、基本信息
@@ -71,17 +71,9 @@ class BeanPostProcessor {
class InstantiationAwareBeanPostProcessor {
<>
-}
-class Ordered {
-<>
-
}
class ProxyConfig
class ProxyProcessorSupport
-class Serializable {
-<>
-
-}
class SmartInstantiationAwareBeanPostProcessor {
<>
@@ -96,45 +88,81 @@ AspectJAwareAdvisorAutoProxyCreator --> AbstractAdvisorAutoProxyCreator
BeanClassLoaderAware --> Aware
BeanFactoryAware --> Aware
InstantiationAwareBeanPostProcessor --> BeanPostProcessor
-ProxyConfig ..> Serializable
ProxyProcessorSupport ..> AopInfrastructureBean
ProxyProcessorSupport ..> BeanClassLoaderAware
-ProxyProcessorSupport ..> Ordered
ProxyProcessorSupport --> ProxyConfig
SmartInstantiationAwareBeanPostProcessor --> InstantiationAwareBeanPostProcessor
~~~
### 五、最佳实践
-`AnnotationAwareAspectJAutoProxyCreator`类以及注解驱动的切面编程。通过注册`AnnotationAwareAspectJAutoProxyCreator`作为Bean,并指定应用程序配置类,Spring容器能够自动创建切面代理,并在运行时织入切面逻辑。最后,从容器中获取`MyService` bean并调用其方法,实现了面向切面编程的横切关注点的功能。
+使用`EnableAspectJAutoProxy`
+注解和Spring的基于注解的应用上下文来启用AspectJ自动代理功能。在程序中,首先创建了一个基于注解的应用上下文,然后通过该上下文获取了`MyService`
+bean,并调用了其方法。
```java
-public class AnnotationAwareAspectJAutoProxyCreatorDemo {
+public class EnableAspectJAutoProxyDemo {
public static void main(String[] args) {
- // 创建一个默认的 Bean 工厂
- AnnotationConfigApplicationContext beanFactory = new AnnotationConfigApplicationContext();
- // 注册AnnotationAwareAspectJAutoProxyCreator作为Bean,用于自动创建切面代理
- beanFactory.registerBeanDefinition("internalAutoProxyCreator", new RootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class));
- // 注册应用程序配置类
- beanFactory.register(AppConfig.class);
- // 刷新应用程序上下文
- beanFactory.refresh();
-
- // 从容器中获取MyService bean
- MyService myService = beanFactory.getBean(MyService.class);
+ // 创建基于注解的应用上下文
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+ // 从应用上下文中获取MyService bean
+ MyService myService = context.getBean(MyService.class);
// 调用MyService的方法
- myService.doSomething();
+ myService.foo();
}
}
```
-运行结果,执行`MyService`中的`doSomething()`方法之前和之后,切面逻辑已成功织入。
+`AppConfig` 类是一个使用 `@Configuration` 注解标记的配置类,通过 `@EnableAspectJAutoProxy` 开启了 AspectJ
+自动代理功能,并通过 `@ComponentScan` 启用了组件扫描,用于自动发现和注册 Spring 组件。
```java
-Before executing the method...
-Doing something...
-After executing the method...
+
+@Configuration
+@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);
}
```
-
-### 八、常见问题
-
-1. **无法注入依赖**
-
- + 可能会遇到无法注入依赖的问题,这通常是由于AOP代理的顺序问题导致的。
-
-2. **切面未生效**
-
- + 有时配置了切面,但是切面并没有生效,可能是由于切面表达式不正确,或者AOP代理配置错误导致的。
-
-
-4. **Bean未被代理**
-
- + 有时候配置了AnnotationAwareAspectJAutoProxyCreator,但是某些Bean并没有被代理,可能是由于Bean的作用域、类型或其他条件不满足自动代理的条件。
\ No newline at end of file
diff --git a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AnnotationAwareAspectJAutoProxyCreatorDemo.java b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AnnotationAwareAspectJAutoProxyCreatorDemo.java
index 2a5e3f3..2608580 100644
--- a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AnnotationAwareAspectJAutoProxyCreatorDemo.java
+++ b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AnnotationAwareAspectJAutoProxyCreatorDemo.java
@@ -1,24 +1,15 @@
package com.xcs.spring;
-import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
-import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AnnotationAwareAspectJAutoProxyCreatorDemo {
public static void main(String[] args) {
- // 创建一个默认的 Bean 工厂
- AnnotationConfigApplicationContext beanFactory = new AnnotationConfigApplicationContext();
- // 注册AnnotationAwareAspectJAutoProxyCreator作为Bean,用于自动创建切面代理
- beanFactory.registerBeanDefinition("internalAutoProxyCreator", new RootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class));
- // 注册应用程序配置类
- beanFactory.register(AppConfig.class);
- // 刷新应用程序上下文
- beanFactory.refresh();
-
- // 从容器中获取MyService bean
- MyService myService = beanFactory.getBean(MyService.class);
+ // 创建基于注解的应用上下文
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+ // 从应用上下文中获取MyService bean
+ MyService myService = context.getBean(MyService.class);
// 调用MyService的方法
- myService.doSomething();
+ myService.foo();
}
}
diff --git a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AppConfig.java b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AppConfig.java
index b33612f..41e9108 100644
--- a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AppConfig.java
+++ b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/AppConfig.java
@@ -2,8 +2,11 @@ package com.xcs.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
-@ComponentScan("com.xcs.spring")
+@EnableAspectJAutoProxy
+@ComponentScan
public class AppConfig {
+
}
diff --git a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyAspect.java b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyAspect.java
index 3baeade..fc285eb 100644
--- a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyAspect.java
+++ b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyAspect.java
@@ -1,21 +1,15 @@
package com.xcs.spring;
-import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
-class MyAspect {
+public class MyAspect {
- @Before("execution(* com.xcs.spring.MyService.doSomething(..))")
+ @Before("execution(* com.xcs.spring.MyService+.*(..))")
public void before() {
- System.out.println("Before executing the method..." );
- }
-
- @After("execution(* com.xcs.spring.MyService.doSomething(..))")
- public void after() {
- System.out.println("After executing the method..." );
+ System.out.println("Before method execution");
}
}
diff --git a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyService.java b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyService.java
index 809682b..ea6a5c3 100644
--- a/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyService.java
+++ b/spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/src/main/java/com/xcs/spring/MyService.java
@@ -4,7 +4,8 @@ import org.springframework.stereotype.Service;
@Service
public class MyService {
- public void doSomething() {
- System.out.println("Doing something...");
+
+ public void foo() {
+ System.out.println("foo...");
}
}
diff --git a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md
index a887d9c..ad5a330 100644
--- a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md
+++ b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md
@@ -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
public class BeanFactoryAdvisorRetrievalHelperDemo {
public static void main(String[] args) {
- // 创建一个默认的 Bean 工厂
- DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- // 向 Bean 工厂注册一个名为 "myAdvisor" 的 Advisor
- beanFactory.registerSingleton("myAdvisor", new MyAdvisor());
-
- // 创建 BeanFactoryAdvisorRetrievalHelper 实例,并传入 Bean 工厂
- BeanFactoryAdvisorRetrievalHelper helper = new BeanFactoryAdvisorRetrievalHelper(beanFactory);
- // 获取 Bean 工厂中的 Advisor 列表
- List advisors = helper.findAdvisorBeans();
- // 打印 Advisors
- advisors.forEach(System.out::println);
+ // 创建基于注解的应用上下文
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+ // 从应用上下文中获取MyService bean
+ MyService myService = context.getBean(MyService.class);
+ // 调用MyService的方法
+ myService.foo();
}
}
```
-`MyAdvisor` 类是一个自定义的 Advisor,继承自 `AbstractPointcutAdvisor`,用于定义切面的逻辑。在该类中,`getPointcut()` 方法返回一个始终为真的 Pointcut,表示适用于所有的连接点;`getAdvice()` 方法返回一个空的 Advice,表示不对目标方法添加任何额外的通知逻辑。因此,该 Advisor 没有实际的业务逻辑,仅作为演示目的。
+`AppConfig` 类是一个使用 `@Configuration` 注解标记的配置类,通过 `@EnableAspectJAutoProxy` 开启了 AspectJ
+自动代理功能,并通过 `@ComponentScan` 启用了组件扫描,用于自动发现和注册 Spring 组件。
```java
+
+@Configuration
+@EnableAspectJAutoProxy
+@ComponentScan
+public class AppConfig {
+
+}
+```
+
+使用 `@Component` 注解标记的自定义 Advisor,继承自 `AbstractPointcutAdvisor`。它定义了一个总是返回真值的 Pointcut,并将一个自定义的
+Advice `MyAdvice` 应用于目标方法上。
+
+```java
+
+@Component
public class MyAdvisor extends AbstractPointcutAdvisor {
@Override
@@ -66,18 +80,67 @@ public class MyAdvisor extends AbstractPointcutAdvisor {
@Override
public Advice getAdvice() {
- return Advisor.EMPTY_ADVICE;
+ return new MyAdvice();
}
}
```
-运行结果,成功地从 Bean 工厂中获取了Advisor。
+`MyAdvice` 类是一个实现了 `MethodBeforeAdvice` 接口的自定义通知类,用于在目标方法执行前执行特定逻辑。在 `before()`
+方法中,它打印了一条消息:"Before method execution"。
```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 的列表。
@@ -142,21 +205,3 @@ public List findAdvisorBeans() {
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 时,需要更新缓存以确保数据的一致性。
\ No newline at end of file
diff --git a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/AppConfig.java b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/AppConfig.java
new file mode 100644
index 0000000..41e9108
--- /dev/null
+++ b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/AppConfig.java
@@ -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 {
+
+}
diff --git a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/BeanFactoryAdvisorRetrievalHelperDemo.java b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/BeanFactoryAdvisorRetrievalHelperDemo.java
index 95ee8f5..fabb5df 100644
--- a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/BeanFactoryAdvisorRetrievalHelperDemo.java
+++ b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/BeanFactoryAdvisorRetrievalHelperDemo.java
@@ -1,24 +1,15 @@
package com.xcs.spring;
-import org.springframework.aop.Advisor;
-import org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-
-import java.util.List;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BeanFactoryAdvisorRetrievalHelperDemo {
public static void main(String[] args) {
- // 创建一个默认的 Bean 工厂
- DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- // 向 Bean 工厂注册一个名为 "myAspect" 的 Advisor
- beanFactory.registerSingleton("myAspect", new MyAdvisor());
-
- // 创建 BeanFactoryAdvisorRetrievalHelper 实例,并传入 Bean 工厂
- BeanFactoryAdvisorRetrievalHelper helper = new BeanFactoryAdvisorRetrievalHelper(beanFactory);
- // 获取 Bean 工厂中的 Advisor 列表
- List advisors = helper.findAdvisorBeans();
- // 打印 Advisors
- advisors.forEach(System.out::println);
+ // 创建基于注解的应用上下文
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+ // 从应用上下文中获取MyService bean
+ MyService myService = context.getBean(MyService.class);
+ // 调用MyService的方法
+ myService.foo();
}
}
diff --git a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyAdvice.java b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyAdvice.java
new file mode 100644
index 0000000..a206564
--- /dev/null
+++ b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyAdvice.java
@@ -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");
+ }
+}
diff --git a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyAdvisor.java b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyAdvisor.java
index df3aca9..55c7855 100644
--- a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyAdvisor.java
+++ b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyAdvisor.java
@@ -1,10 +1,11 @@
package com.xcs.spring;
import org.aopalliance.aop.Advice;
-import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
+import org.springframework.stereotype.Component;
+@Component
public class MyAdvisor extends AbstractPointcutAdvisor {
@Override
@@ -14,6 +15,6 @@ public class MyAdvisor extends AbstractPointcutAdvisor {
@Override
public Advice getAdvice() {
- return Advisor.EMPTY_ADVICE;
+ return new MyAdvice();
}
}
diff --git a/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyService.java b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyService.java
new file mode 100644
index 0000000..ea6a5c3
--- /dev/null
+++ b/spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/src/main/java/com/xcs/spring/MyService.java
@@ -0,0 +1,11 @@
+package com.xcs.spring;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class MyService {
+
+ public void foo() {
+ System.out.println("foo...");
+ }
+}
diff --git a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md
index 5dee7ab..09d6a00 100644
--- a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md
+++ b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md
@@ -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
public class BeanFactoryAspectJAdvisorsBuilderDemo {
public static void main(String[] args) {
- // 创建一个默认的 Bean 工厂
- DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- // 在 Bean 工厂中注册一个名为 "myAspect" 的单例 Bean,类型为 MyAspect
- beanFactory.registerSingleton("myAspect", new MyAspect());
-
- // 创建 BeanFactoryAspectJAdvisorsBuilder 实例,并传入 Bean 工厂和 ReflectiveAspectJAdvisorFactory 实例
- BeanFactoryAspectJAdvisorsBuilder builder = new BeanFactoryAspectJAdvisorsBuilder(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
- // 构建 AspectJ Advisors
- List advisors = builder.buildAspectJAdvisors();
- // 打印 Advisors
- advisors.forEach(System.out::println);
+ // 创建基于注解的应用上下文
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+ // 从应用上下文中获取MyService bean
+ MyService myService = context.getBean(MyService.class);
+ // 调用MyService的方法
+ myService.foo();
}
}
```
-使用了 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
@Aspect
+@Component
class MyAspect {
- @Before("execution(* com.xcs.spring.MyService.doSomething(..))")
+ @Before("execution(* com.xcs.spring.MyService.foo(..))")
public void before() {
- System.out.println("Before executing the method..." );
- }
-
- @After("execution(* com.xcs.spring.MyService.doSomething(..))")
- public void after() {
- System.out.println("After executing the method..." );
+ System.out.println("Before method execution");
}
}
```
-定义了一个名为 `MyService` 的简单 Java 类,其中包含一个名为 `doSomething()` 的方法。该方法简单地打印一条日志信息 "Doing something..."。这个类作为示例类使用,用来演示在 AOP 中如何应用切面逻辑。
+`MyService` 类是一个使用 `@Service` 注解标记的服务类,提供了一个名为 `foo()` 的方法,该方法在调用时会打印消息 "foo..."。
```java
+
+@Service
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
-InstantiationModelAwarePointcutAdvisor: expression [execution(* com.xcs.spring.MyService.doSomething(..))]; advice method [public void com.xcs.spring.MyAspect.before()]; perClauseKind=SINGLETON
-InstantiationModelAwarePointcutAdvisor: expression [execution(* com.xcs.spring.MyService.doSomething(..))]; advice method [public void com.xcs.spring.MyAspect.after()]; perClauseKind=SINGLETON
+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->>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,以提高性能。
@@ -226,8 +258,5 @@ private boolean hasAspectAnnotation(Class> clazz) {
}
```
-### 六、常见问题
-1. **实例化模型匹配**
- + 在判断切面的实例化模型时,需要确保该模型与实际的 Bean 实例化策略相匹配。如果切面 Bean 被声明为单例模式,但实际上是多例的,或者反之,则可能会导致不一致或异常情况。
\ No newline at end of file
diff --git a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/AppConfig.java b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/AppConfig.java
new file mode 100644
index 0000000..41e9108
--- /dev/null
+++ b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/AppConfig.java
@@ -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 {
+
+}
diff --git a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/BeanFactoryAspectJAdvisorsBuilderDemo.java b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/BeanFactoryAspectJAdvisorsBuilderDemo.java
index c9cbe89..582eb65 100644
--- a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/BeanFactoryAspectJAdvisorsBuilderDemo.java
+++ b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/BeanFactoryAspectJAdvisorsBuilderDemo.java
@@ -1,25 +1,15 @@
package com.xcs.spring;
-import org.springframework.aop.Advisor;
-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;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BeanFactoryAspectJAdvisorsBuilderDemo {
public static void main(String[] args) {
- // 创建一个默认的 Bean 工厂
- DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- // 在 Bean 工厂中注册一个名为 "myAspect" 的单例 Bean,类型为 MyAspect
- beanFactory.registerSingleton("myAspect", new MyAspect());
-
- // 创建 BeanFactoryAspectJAdvisorsBuilder 实例,并传入 Bean 工厂和 ReflectiveAspectJAdvisorFactory 实例
- BeanFactoryAspectJAdvisorsBuilder builder = new BeanFactoryAspectJAdvisorsBuilder(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
- // 构建 AspectJ Advisors
- List advisors = builder.buildAspectJAdvisors();
- // 打印 Advisors
- advisors.forEach(System.out::println);
+ // 创建基于注解的应用上下文
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
+ // 从应用上下文中获取MyService bean
+ MyService myService = context.getBean(MyService.class);
+ // 调用MyService的方法
+ myService.foo();
}
}
diff --git a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyAspect.java b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyAspect.java
index 4c37fd5..18c136f 100644
--- a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyAspect.java
+++ b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyAspect.java
@@ -1,19 +1,15 @@
package com.xcs.spring;
-import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
@Aspect
+@Component
class MyAspect {
- @Before("execution(* com.xcs.spring.MyService.doSomething(..))")
+ @Before("execution(* com.xcs.spring.MyService.foo(..))")
public void before() {
- System.out.println("Before executing the method..." );
- }
-
- @After("execution(* com.xcs.spring.MyService.doSomething(..))")
- public void after() {
- System.out.println("After executing the method..." );
+ System.out.println("Before method execution");
}
}
diff --git a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyService.java b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyService.java
index 843fa2c..8099049 100644
--- a/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyService.java
+++ b/spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/src/main/java/com/xcs/spring/MyService.java
@@ -1,7 +1,10 @@
package com.xcs.spring;
+import org.springframework.stereotype.Service;
+
+@Service
public class MyService {
- public void doSomething() {
- System.out.println("Doing something...");
+ public void foo() {
+ System.out.println("foo...");
}
}
diff --git a/spring-aop/spring-aop-enableAspectJAutoProxy/README.md b/spring-aop/spring-aop-enableAspectJAutoProxy/README.md
index 99a2b26..d10d61d 100644
--- a/spring-aop/spring-aop-enableAspectJAutoProxy/README.md
+++ b/spring-aop/spring-aop-enableAspectJAutoProxy/README.md
@@ -1,13 +1,13 @@
## @EnableAspectJAutoProxy
-- [@EnableAspectJAutoProxy](#@EnableAspectJAutoProxy)
+- [@EnableAspectJAutoProxy](#enableaspectjautoproxy)
- [一、基本信息](#一基本信息)
- [二、基本描述](#二基本描述)
- [三、主要功能](#三主要功能)
- - [四、注解源码](#注解源码)
+ - [四、注解源码](#四注解源码)
- [五、最佳实践](#五最佳实践)
- [六、源码分析](#六源码分析)
- - [七、常见问题](#七常见问题)
+
### 一、基本信息
@@ -175,30 +175,23 @@ public class EnableAspectJAutoProxyDemo {
}
```
-通过`@Configuration`注解表示它是一个配置类,用于配置Spring应用的bean。其中,通过`@EnableAspectJAutoProxy`
-注解启用了AspectJ自动代理功能,使得Spring能够自动处理切面。在配置中定义了两个bean:`MyService`和`MyAspect`
-,分别用于创建`MyService`的实例和`MyAspect`切面的实例。
+`AppConfig` 类是一个使用 `@Configuration` 注解标记的配置类,通过 `@EnableAspectJAutoProxy` 开启了 AspectJ
+自动代理功能,并通过 `@ComponentScan` 启用了组件扫描,用于自动发现和注册 Spring 组件。
```java
@Configuration
@EnableAspectJAutoProxy
+@ComponentScan
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
+
+@Service
public class MyService {
public void foo() {
@@ -211,6 +204,7 @@ public class MyService {
```java
@Aspect
+@Component
public class MyAspect {
@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。
@@ -260,6 +263,8 @@ public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessar
在`org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry,source)`方法中,注册AspectJ注解自动代理创建器,并且可以指定源对象。在方法中,它调用了一个辅助方法`registerOrEscalateApcAsRequired`,该方法会根据需要注册或升级AspectJ注解自动代理创建器,并返回相应的BeanDefinition。
+[AnnotationAwareAspectJAutoProxyCreator源码分析](../spring-aop-annotationAwareAspectJAutoProxyCreator/README.md)
+
```java
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
diff --git a/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/AppConfig.java b/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/AppConfig.java
index e8e9765..41e9108 100644
--- a/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/AppConfig.java
+++ b/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/AppConfig.java
@@ -1,20 +1,12 @@
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.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
+@ComponentScan
public class AppConfig {
- @Bean
- public MyService myService() {
- return new MyService();
- }
-
- @Bean
- public MyAspect myAspect() {
- return new MyAspect();
- }
}
diff --git a/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyAspect.java b/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyAspect.java
index fd58ec4..fc285eb 100644
--- a/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyAspect.java
+++ b/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyAspect.java
@@ -2,8 +2,10 @@ package com.xcs.spring;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
@Aspect
+@Component
public class MyAspect {
@Before("execution(* com.xcs.spring.MyService+.*(..))")
diff --git a/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyService.java b/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyService.java
index b4047e7..ea6a5c3 100644
--- a/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyService.java
+++ b/spring-aop/spring-aop-enableAspectJAutoProxy/src/main/java/com/xcs/spring/MyService.java
@@ -1,5 +1,8 @@
package com.xcs.spring;
+import org.springframework.stereotype.Service;
+
+@Service
public class MyService {
public void foo() {