简单demo:
github
自定义切面MyAspect
@Aspect
@Component
@EnableAspectJAutoProxy
public class MyAspect {
@Pointcut(value = "execution(* com.tianwen.spring.service..*.*d1(..))")
public void pointcut() {}
@Around(value = "pointcut()")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("before...");
proceedingJoinPoint.proceed();
System.out.println("after...");
}
接口TestServiceI
public interface TestServiceI {
void method1();
void method2();
}
实现类TestServiceA
@Service
public class TestServiceA implements TestServiceI {
@Override
public void method1() {
System.out.println("TestServiceA method1...");
}
@Override
public void method2() {
System.out.println("TestServiceA method2...");
}
}
另一个没有实现接口的ServiceTestServiceB
@Service
public class TestServiceB {
public void method1() {
System.out.println("TestServiceB method1...");
}
}
运行测试类Aop
public class Aop {
@Test
public void test1() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.tianwen.spring");
TestServiceI testServiceI = (TestServiceI) context.getBean("testServiceA");
testServiceI.method1();
System.out.println("---");
testServiceI.method2();
System.out.println("---");
TestServiceB testServiceB = (TestServiceB) context.getBean("testServiceB");
testServiceB.method1();
}
}
运行结果
before...
TestServiceA method1...
after...
---
TestServiceA method2...
---
before...
TestServiceB method1...
after...
分析:
@EnableAspectJAutoProxy
此注解不一定要在MyAspect
这个类上,标注在任何一个可以被容器扫描到的类上即可,例如标注在TestServiceB
上。
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.tianwen.spring");
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
在无参构造器中,new AnnotatedBeanDefinitionReader()
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
有向容器注册ConfigurationClassPostProcessor
类,这是一个BeanFactoryPostProcessor
,在容器创建过程中会被调用。
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
- 在
AnnotationConfigApplicationContext
构造器中调用的refresh()
方法,实为AbstractApplicationContext
的refresh()
方法。
public void refresh() throws BeansException, IllegalStateException {
...
invokeBeanFactoryPostProcessors(beanFactory);
...
}
关注refresh()
中的invokeBeanFactoryPostProcessors()
,其目的是为了执行所有的BeanFactoryPostProcessor
。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
委派类PostProcessorRegistrationDelegate
的invokeBeanFactoryPostProcessors
方法。
先根据类型获取到所有的BeanDefinitionRegistryPostProcessor
,获取到了1中向容器注册的ConfigurationClassPostProcessor
类,因为其实现了接口PriorityOrdered
,优先执行。
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
...
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
...
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
...
invokeBeanDefinitionRegistryPostProcessors
方法中执行这些postProcessor
的postProcessBeanDefinitionRegistry
方法。
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
-
ConfigurationClassPostProcessor
用来处理所有扫描到的配置类,其postProcessBeanDefinitionRegistry
中
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
关注processConfigBeanDefinitions
方法。在处理扫描到的配置类时(配置类分为完全配置类和不完全配置类,都会在这个过程中处理)
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
...
this.reader.loadBeanDefinitions(configClasses);
}
loadBeanDefinitionsForConfigurationClass
方法
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
loadBeanDefinitionsForConfigurationClass
,在处理到MyAspect
时,获取到类上标注的注解@EnableAspectJAutoProxy
,该注解内有@Import(AspectJAutoProxyRegistrar.class)
,AspectJAutoProxyRegistrar
是一个ImportBeanDefinitionRegistrar
。
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
TrackedConditionEvaluator trackedConditionEvaluator) {
...
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
loadBeanDefinitionsFromRegistrars
调用对应的registerBeanDefinitions方法
,即类AspectJAutoProxyRegistrar
的registerBeanDefinitions
方法。
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> entry : registrars.entrySet()) {
entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
}
}
AspectJAutoProxyRegistrar
的registerBeanDefinitions
方法中向容器注册AnnotationAwareAspectJAutoProxyCreator
,这是一个BeanPostProcessor
(注意区分BeanFactoryPostProcessor
和BeanPostProcessor
)
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
- 回到
refresh()
方法中看finishBeanFactoryInitialization()
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
...
beanFactory.preInstantiateSingletons();
}
在DefaultListableBeanFactory
的preInstantiateSingletons()
方法中,会对需要被创建的bean进行创建。
public void preInstantiateSingletons() throws BeansException {
...
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
...
getBean(beanName);
}
这是一个容器创建bean的过程,
getBean->doGetBean->createBean
在AbstractAutowireCapableBeanFactory
的createBean
方法中,尝试返回代理类。
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
...
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
AbstractAutowireCapableBeanFactory
的resolveBeforeInstantiation
方法
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
...
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
...
return bean;
}
在applyBeanPostProcessorsBeforeInstantiation
中执行所有的InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation
方法
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
因为InstantiationAwareBeanPostProcessor
是AnnotationAwareAspectJAutoProxyCreator
的基类:
所以这里会执行上述向容器注册的AnnotationAwareAspectJAutoProxyCreator
的postProcessBeforeInstantiation
方法,实际调用基类AbstractAutoProxyCreator
的对应方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
...
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
...
}
在shouldSkip
方法中,获取合适的通知器。
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
...
}
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
在BeanFactoryAspectJAdvisorsBuilder
的buildAspectJAdvisors
中,取得所有的beanName,使用isAspect
方法判断其是否属于切面,取得通知器。
public List<Advisor> buildAspectJAdvisors() {
...
for (String beanName : beanNames) {
...
if (this.advisorFactory.isAspect(beanType)) {
...
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
AbstractAspectJAdvisorFactory
中的isAspect
方法
@Override
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
ReflectiveAspectJAdvisorFactory
中的getAdvisors
方法。取得切面上的切点与通知器。通知器类型为InstantiationModelAwarePointcutAdvisorImpl
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
...
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
}
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
...
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
...
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
此时,自定义的MyAspect
上的@Aspect
注解生效,被判断为一个通知器,加入到通知器List中。
再回到容器创建bean的过程中,在AbstractAutowireCapableBeanFactory
createBean
方法,doCreateBean
方法,initializeBean
方法,applyBeanPostProcessorsAfterInitialization
方法。执行BeanPostProcessor
的后置方法。
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
...
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
...
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
...
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
所以这里会执行上述向容器注册的AnnotationAwareAspectJAutoProxyCreator
的的postProcessAfterInitialization
方法,实际调用基类AbstractAutoProxyCreator
的对应方法
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
...
return wrapIfNecessary(bean, beanName, cacheKey);
}
在wrapIfNecessary
方法中,getAdvicesAndAdvisorsForBean
,findEligibleAdvisors
内取得合适的通知器。判断这些通知器是否适用当前bean。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
}
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
...
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
...
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
}
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
...
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
最终在AopUtils
的findAdvisorsThatCanApply
,canApply
方法中,获取到切点(AspectJExpressionPointcut
)的方法匹配器,对当前bean的方法逐个匹配,一旦匹配到,返回true。外层会返回对应的通知器,进而可得知需要为当前bean创建代理对象。是否需要为bean创建aop的代理对象,就是由此判断得知。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
MethodMatcher methodMatcher = pc.getMethodMatcher();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
return false;
}
createProxy
中使用ProxyFactory
创建代理对象。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
而关于ProxyFactory
如何创建代理对象,调用代理对象时,切面上的方法如何工作,与之前分析的ProxyFactoryBean
流程大体一致。
总结:
- 容器创建过程中,默认会向容器中注册
ConfigurationClassPostProcessor
类,一个BeanFactoryPostProcessor
,以用来处理所有扫描到的配置类。 - 容器创建过程中,在处理到被
@EnableAspectJAutoProxy
标注的类,解析该类注解时,对于@EnableAspectJAutoProxy
上的@Import(AspectJAutoProxyRegistrar.class)
的处理。会向容器中注册AnnotationAwareAspectJAutoProxyCreator
,一个BeanPostProcessor
。(注意区分BeanFactoryPostProcessor
与BeanPostProcessor
) - 容器完成创建后,会对不需要延迟注册的bean提前完成注册。
- 在bean的创建过程中,在
AbstractAutowireCapableBeanFactory
的createBean
的resolveBeforeInstantiation
方法中,执行beanPostProcessor
的postProcessBeforeInstantiation
方法时。上一步往容器中注册的AnnotationAwareAspectJAutoProxyCreator
会工作,在执行其从基类AbstractAutoProxyCreator
继承过来的postProcessBeforeInstantiation
方法时,收集容器中所有的bean通知器。关于是否为通知器的判断方法在AbstractAspectJAdvisorFactory
的isAspect
方法中。 - 在bean的创建过程中,在
AbstractAutowireCapableBeanFactory
的doCreateBean
的initializeBean
方法中,执行所有beanPostProcessor
的postProcessAfterInitialization
方法。所以,AbstractAutoProxyCreator
的postProcessAfterInitialization
方法会被执行,最终执行的是wrapIfNecessary
方法。在该方法内,获取到配置的通知器,对每一个需要向容器注册的bean,用通知器上的切点的匹配规则对当前bean的方法逐个匹配,如果至少有一个方法匹配,说明需要创建代理对象,则使用ProxyFactory
完成代理对象的创建(与之前分析的ProxyFactoryBean
流程大体一致)。如果全部不匹配,返回普通bean。 - 最终在方法调用时,如果是普通bean只是简单的方法调用,但如果是代理对象,方法调用过程中还伴随着织入的逻辑。至于这些逻辑如何工作。与之前分析的
ProxyFactoryBean
流程大体一致。 - 目前看起来,上述方式的springAop配置,只是仅仅使用到了AspectJ的注解。
网友评论