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>
|
||||
- [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>
|
||||
- [@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>
|
||||
- [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>
|
||||
- [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>
|
||||
- [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>
|
||||
- [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)
|
||||
- [一、基本信息](#一基本信息)
|
||||
- [二、基本描述](#二基本描述)
|
||||
|
@ -7,7 +8,6 @@
|
|||
- [五、最佳实践](#五最佳实践)
|
||||
- [六、时序图](#六时序图)
|
||||
- [七、源码分析](#七源码分析)
|
||||
- [八、常见问题](#八常见问题)
|
||||
|
||||
### 一、基本信息
|
||||
|
||||
|
@ -71,17 +71,9 @@ class BeanPostProcessor {
|
|||
class InstantiationAwareBeanPostProcessor {
|
||||
<<Interface>>
|
||||
|
||||
}
|
||||
class Ordered {
|
||||
<<Interface>>
|
||||
|
||||
}
|
||||
class ProxyConfig
|
||||
class ProxyProcessorSupport
|
||||
class Serializable {
|
||||
<<Interface>>
|
||||
|
||||
}
|
||||
class SmartInstantiationAwareBeanPostProcessor {
|
||||
<<Interface>>
|
||||
|
||||
|
@ -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的作用域、类型或其他条件不满足自动代理的条件。
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Advisor> 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<Advisor> 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 时,需要更新缓存以确保数据的一致性。
|
|
@ -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;
|
||||
|
||||
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<Advisor> 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
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<Advisor> 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 被声明为单例模式,但实际上是多例的,或者反之,则可能会导致不一致或异常情况。
|
|
@ -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;
|
||||
|
||||
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<Advisor> 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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+.*(..))")
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.xcs.spring;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class MyService {
|
||||
|
||||
public void foo() {
|
||||
|
|
Loading…
Reference in New Issue