个人随笔
目录
一个简单的例子来探寻SpringAOP执行源码的主脉络(一):创建代理对象
2021-07-21 22:55:29

在上几篇文章中,我们知道了SpringIOC的大概原理,通过源码把spring从加载配置文件到解析配置文件到实例化过程走了一遍,那这一篇文章我想要尝试下弄明白Spring是怎么实现AOP的?完全通过自己的推测来从源码找答案。

一、AOP例子

要弄明白AOP的实现原理,我们得先看看AOP的功能

1、引入依赖

  1. <!-- aspectJ AOP 织入器 -->
  2. <dependency>
  3. <groupId>org.aspectj</groupId>
  4. <artifactId>aspectjweaver</artifactId>
  5. <version>1.8.9</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-spring-context -->
  8. <dependency>

2、配置类加上注解开启AOP

  1. @Configuration
  2. @ComponentScan(basePackages = "com.suibibk.spring")
  3. @EnableAspectJAutoProxy
  4. public class SpringConfiguration {
  5. //spring容器初始化时,会调用配置类的无参构造函数
  6. public SpringConfiguration(){
  7. System.out.println("容器启动初始化");
  8. }
  9. }

3、业务类

  1. package com.suibibk.spring.service;
  2. public interface UserService {
  3. public void test();
  4. }
  1. package com.suibibk.spring.service;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class UserServiceImpl implements UserService {
  5. public void test() {
  6. System.out.println("就是这么拽");
  7. }
  8. }

4、切面

  1. @Aspect
  2. @Component
  3. public class MyAspect {
  4. @Pointcut("execution(public * com.suibibk.spring.service.*.*(..))")
  5. public void web() {
  6. }
  7. @Around("web()")
  8. public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
  9. System.out.println("之前");
  10. Object obj =pjp.proceed();
  11. System.out.println("之后");
  12. return obj;
  13. }
  14. }

5、启动类

  1. public class App {
  2. public static void main(String[] args) {
  3. ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
  4. UserService userService = (UserService) context.getBean("userServiceImpl");
  5. userService.test();
  6. }
  7. }

6、测试结果

  1. 容器启动初始化
  2. 之前
  3. 就是这么拽
  4. 之后

完美符合预期,在执行业务逻辑前后加上了额外的业务逻辑。

那怎么实现的呢?

二、从什么地方下手?

那我们从什么地方开始阅读源码呢,按我阅读源码的习惯,我是喜欢推测+调试相结合,比如我们前面知道了spring实例化的过程,而AOP肯定是用了动态代理的模式,也就是把正真的bean对象进行了代理包装,也就是肯定是生成了bean对象后包装的,那在实例化后什么地方还会对bean进行增强呢,我们从前面IOC spring 实例化源码知道,有几个地方对这个bean进行包装,这些bean都实现了BeanPostProcessor接口,然后在postProcessBeforeInitialization和postProcessAfterInitialization方法进行处理,我们研究下AOP注解有没有这些,或者有哪一个关键的实现了BeanPostProcessor的类,可以去AOP包下面看看。

1、先看看AOP开启注解有没有什么特殊

  1. @EnableAspectJAutoProxy
  2. public class SpringConfiguration {
  3. //spring容器初始化时,会调用配置类的无参构造函数
  4. public SpringConfiguration(){
  5. System.out.println("容器启动初始化");
  6. }
  7. }

进入@EnableAspectJAutoProxy 看看,记住我们的目标是根据上面的推测找到某些与AOP有关的实现了BeanPostProcessor接口的类,继续点进去看看。

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(AspectJAutoProxyRegistrar.class)
  5. public @interface EnableAspectJAutoProxy

我们看到了@Import注解,这个注解效果跟@Bean@Component的最终效果一样,都是生成一个bean,这里生成的是

  1. AspectJAutoProxyRegistrar.class

这个我们是在上几篇文章中的源码里看过的:https://www.suibibk.com/topic/866818869614870528 ,如下

  1. @Nullable
  2. protected final SourceClass doProcessConfigurationClass(
  3. ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
  4. throws IOException {
  5. if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
  6. // Recursively process any member (nested) classes first
  7. processMemberClasses(configClass, sourceClass, filter);
  8. }
  9. // Process any @PropertySource annotations
  10. for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
  11. sourceClass.getMetadata(), PropertySources.class,
  12. org.springframework.context.annotation.PropertySource.class)) {
  13. if (this.environment instanceof ConfigurableEnvironment) {
  14. processPropertySource(propertySource);
  15. }
  16. else {
  17. logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
  18. "]. Reason: Environment must implement ConfigurableEnvironment");
  19. }
  20. }
  21. // Process any @ComponentScan annotations
  22. Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
  23. sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
  24. if (!componentScans.isEmpty() &&
  25. !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
  26. for (AnnotationAttributes componentScan : componentScans) {
  27. // The config class is annotated with @ComponentScan -> perform the scan immediately
  28. Set<BeanDefinitionHolder> scannedBeanDefinitions =
  29. this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
  30. // Check the set of scanned definitions for any further config classes and parse recursively if needed
  31. for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
  32. BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
  33. if (bdCand == null) {
  34. bdCand = holder.getBeanDefinition();
  35. }
  36. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
  37. parse(bdCand.getBeanClassName(), holder.getBeanName());
  38. }
  39. }
  40. }
  41. }
  42. // Process any @Import annotations
  43. processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
  44. // Process any @ImportResource annotations
  45. AnnotationAttributes importResource =
  46. AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
  47. if (importResource != null) {
  48. String[] resources = importResource.getStringArray("locations");
  49. Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
  50. for (String resource : resources) {
  51. String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
  52. configClass.addImportedResource(resolvedResource, readerClass);
  53. }
  54. }
  55. // Process individual @Bean methods
  56. Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
  57. for (MethodMetadata methodMetadata : beanMethods) {
  58. configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
  59. }
  60. // Process default methods on interfaces
  61. processInterfaces(configClass, sourceClass);
  62. // Process superclass, if any
  63. if (sourceClass.getMetadata().hasSuperClass()) {
  64. String superclass = sourceClass.getMetadata().getSuperClassName();
  65. if (superclass != null && !superclass.startsWith("java") &&
  66. !this.knownSuperclasses.containsKey(superclass)) {
  67. this.knownSuperclasses.put(superclass, configClass);
  68. // Superclass found, return its annotation metadata and recurse
  69. return sourceClass.getSuperClass();
  70. }
  71. }
  72. // No superclass -> processing is complete
  73. return null;
  74. }

我们那时候只关注了@ComponentScan ,其实可以看到后面有Process any @Import annotations ,所以这里推测效果一样,我们继续点进去,看看它实例化的bean是啥

  1. /**
  2. * Registers an {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
  3. * AnnotationAwareAspectJAutoProxyCreator} against the current {@link BeanDefinitionRegistry}
  4. * as appropriate based on a given @{@link EnableAspectJAutoProxy} annotation.
  5. *
  6. * @author Chris Beams
  7. * @author Juergen Hoeller
  8. * @since 3.1
  9. * @see EnableAspectJAutoProxy
  10. */
  11. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  12. /**
  13. * Register, escalate, and configure the AspectJ auto proxy creator based on the value
  14. * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
  15. * {@code @Configuration} class.
  16. */
  17. @Override
  18. public void registerBeanDefinitions(
  19. AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  20. AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
  21. AnnotationAttributes enableAspectJAutoProxy =
  22. AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
  23. if (enableAspectJAutoProxy != null) {
  24. if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
  25. AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
  26. }
  27. if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
  28. AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
  29. }
  30. }
  31. }
  32. }

到这里有点懵,就这?那registerBeanDefinitions方法什么时候调用的呢?此时我们可以在这里打个断点,看看这个方法什么时候调用的。通过断点调试,然后跳出这个方法我们发现回到了熟悉的解析配置类那里

  1. do {
  2. parser.parse(candidates);
  3. parser.validate();
  4. Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
  5. configClasses.removeAll(alreadyParsed);
  6. // Read the model and create bean definitions based on its content
  7. if (this.reader == null) {
  8. this.reader = new ConfigurationClassBeanDefinitionReader(
  9. registry, this.sourceExtractor, this.resourceLoader, this.environment,
  10. this.importBeanNameGenerator, parser.getImportRegistry());
  11. }
  12. this.reader.loadBeanDefinitions(configClasses);
  13. alreadyParsed.addAll(configClasses);
  14. ...
  1. this.reader.loadBeanDefinitions(configClasses);

在这里做了调用,也就是解析完配置类就做了这个调用了,这里我们不去了解具体怎么调用先,我们的目的不在这,我们只要知道spring在这个地方进行了合理的调用就好了。

然后我们回到上面看第一行代码

  1. AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

貌似注册了个啥,到registry中,我们知道registry就是DefaultListableBeanFactory,这里可以推测应该是注册了一个什么类到DefaultListableBeanFactory中的beanDefinitionMap中,key为bean的名称,值为beanDefinition放的应该是这些后置处理器的相关类定义,这里可以直接推测是后置处理器,也就是实现了BeanPostProcessor接口的类,毕竟不实现这个接口的话,在实例化完执行

  1. exposedObject = initializeBean(beanName, exposedObject, mbd);

里面的

  1. if (mbd == null || !mbd.isSynthetic()) {
  2. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  3. }

  1. if (mbd == null || !mbd.isSynthetic()) {
  2. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  3. }

将不能对所有的目标bean进行增强。
我们点进去看看

  1. @Nullable
  2. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
  3. return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
  4. }
  1. @Nullable
  2. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  3. BeanDefinitionRegistry registry, @Nullable Object source) {
  4. return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
  5. }
  1. @Nullable
  2. private static BeanDefinition registerOrEscalateApcAsRequired(
  3. Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
  4. Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
  5. if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
  6. BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
  7. if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
  8. int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
  9. int requiredPriority = findPriorityForClass(cls);
  10. if (currentPriority < requiredPriority) {
  11. apcDefinition.setBeanClassName(cls.getName());
  12. }
  13. }
  14. return null;
  15. }
  16. RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
  17. beanDefinition.setSource(source);
  18. beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
  19. beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  20. registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
  21. return beanDefinition;
  22. }

不出意料这里果然有熟悉的代码

  1. RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
  2. beanDefinition.setSource(source);
  3. beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
  4. beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  5. registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
  6. return beanDefinition;

那这个cls是关键,cls是上面传进来的AnnotationAwareAspectJAutoProxyCreator.class。我们看看这个类的继承关系,看看是否是我们的目标类。

  1. public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator
  2. public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
  3. public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator
  4. public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
  5. public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
  6. public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
  7. public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
  8. public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor

我去,这也太复杂了,不过好歹看到了我们的目标BeanPostProcessor,我们看看那个类有我们的这两个方法

  1. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
  2. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException

最终我们在AbstractAutoProxyCreator.class中找到了目标

  1. @Override
  2. public Object postProcessBeforeInitialization(Object bean, String beanName) {
  3. return bean;
  4. }
  5. ...
  6. /**
  7. * Create a proxy with the configured interceptors if the bean is
  8. * identified as one to proxy by the subclass.
  9. * @see #getAdvicesAndAdvisorsForBean
  10. */
  11. @Override
  12. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  13. if (bean != null) {
  14. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  15. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  16. return wrapIfNecessary(bean, beanName, cacheKey);
  17. }
  18. }
  19. return bean;
  20. }

postProcessBeforeInitialization方法只是简单的返回了bean,关键点在postProcessAfterInitialization方法,也是肯定要在最后进行包装才对,我们为了确认是不是在

  1. if (mbd == null || !mbd.isSynthetic()) {
  2. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  3. }

这里调用的,可以打个断点试试,经过测试,就是从这里进去执行的,所以我们接下来只需要分析

  1. /**
  2. * Create a proxy with the configured interceptors if the bean is
  3. * identified as one to proxy by the subclass.
  4. * @see #getAdvicesAndAdvisorsForBean
  5. */
  6. @Override
  7. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  8. if (bean != null) {
  9. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  10. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  11. return wrapIfNecessary(bean, beanName, cacheKey);
  12. }
  13. }
  14. return bean;
  15. }

来看看spring怎么搞得,怎么把我们的切面给包装进去。

三、怎么生成代理对象的?

我们从上面可以知道,在bean实例化后会调用

  1. exposedObject = initializeBean(beanName, exposedObject, mbd);

来进行初始化,里面会调用

  1. if (mbd == null || !mbd.isSynthetic()) {
  2. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  3. }

来执行一系列的BeanPostProcessors的applyBeanPostProcessorsAfterInitialization方法,而我们的AOP通过@EnableAspectJAutoProxy注解会注入一个bean:AspectJAutoProxyRegistrar.class,spring解析配置类后会调用这个对象的public void registerBeanDefinitions(xxx)方法把一个AnnotationAwareAspectJAutoProxyCreator放入DefaultListableBeanFactory中的beanDefinitionMap中,key为bean的名称,值为beanDefinition放的是这个类的相关类定义,这个类实现了BeanPostProcessor接口。所以关键代码就是这个类的applyBeanPostProcessorsAfterInitialization方法的逻辑,看看是如何对bean进行包装的。

  1. /**
  2. * Create a proxy with the configured interceptors if the bean is:如果bean是,则使用已配置的拦截器创建代理
  3. * identified as one to proxy by the subclass.
  4. * @see #getAdvicesAndAdvisorsForBean
  5. */
  6. @Override
  7. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  8. if (bean != null) {
  9. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  10. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  11. return wrapIfNecessary(bean, beanName, cacheKey);
  12. }
  13. }
  14. return bean;
  15. }

我们看wrapIfNecessary方法

  1. /**
  2. * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.:如果需要,包装给定的bean,也就是说,如果它符合被代理的条件。
  3. * @param bean the raw bean instance
  4. * @param beanName the name of the bean
  5. * @param cacheKey the cache key for metadata access
  6. * @return a proxy wrapping the bean, or the raw bean instance as-is
  7. */
  8. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  9. if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
  10. return bean;
  11. }
  12. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  13. return bean;
  14. }
  15. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  16. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  17. return bean;
  18. }
  19. // Create proxy if we have advice.
  20. //1、如果我们有通知,则创建代理
  21. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  22. if (specificInterceptors != DO_NOT_PROXY) {
  23. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  24. Object proxy = createProxy(
  25. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  26. this.proxyTypes.put(cacheKey, proxy.getClass());
  27. return proxy;
  28. }
  29. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  30. return bean;
  31. }

我们调试,发现specificInterceptors的内容如下:

  1. [org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR, InstantiationModelAwarePointcutAdvisor: expression [web()]; advice method [public java.lang.Object com.suibibk.spring.MyAspect.doAround(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON]

包括我们的

  1. com.suibibk.spring.MyAspect.doAround(org.aspectj.lang.ProceedingJoinPoint)

那这里是怎么解析的呢,是怎么查找到我们定义的切面的,我们来看下方法

  1. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

跟踪进去

  1. @Override
  2. @Nullable
  3. protected Object[] getAdvicesAndAdvisorsForBean(
  4. Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
  5. List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  6. if (advisors.isEmpty()) {
  7. return DO_NOT_PROXY;
  8. }
  9. return advisors.toArray();
  10. }
  1. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  2. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  3. List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  4. extendAdvisors(eligibleAdvisors);
  5. if (!eligibleAdvisors.isEmpty()) {
  6. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  7. }
  8. return eligibleAdvisors;
  9. }

再跟踪进去

  1. @Override
  2. protected List<Advisor> findCandidateAdvisors() {
  3. // Add all the Spring advisors found according to superclass rules.
  4. List<Advisor> advisors = super.findCandidateAdvisors();
  5. // Build Advisors for all AspectJ aspects in the bean factory.
  6. if (this.aspectJAdvisorsBuilder != null) {
  7. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  8. }
  9. return advisors;
  10. }

这我们发现advisors是空的,所以我们看

  1. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());

方法,跟踪进去

  1. public List<Advisor> buildAspectJAdvisors() {
  2. List<String> aspectNames = this.aspectBeanNames;
  3. if (aspectNames == null) {
  4. synchronized (this) {
  5. aspectNames = this.aspectBeanNames;
  6. if (aspectNames == null) {
  7. List<Advisor> advisors = new ArrayList<>();
  8. aspectNames = new ArrayList<>();
  9. String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  10. this.beanFactory, Object.class, true, false);
  11. for (String beanName : beanNames) {
  12. if (!isEligibleBean(beanName)) {
  13. continue;
  14. }
  15. // We must be careful not to instantiate beans eagerly as in this case they
  16. // would be cached by the Spring container but would not have been weaved.
  17. Class<?> beanType = this.beanFactory.getType(beanName);
  18. if (beanType == null) {
  19. continue;
  20. }
  21. if (this.advisorFactory.isAspect(beanType)) {
  22. aspectNames.add(beanName);
  23. AspectMetadata amd = new AspectMetadata(beanType, beanName);
  24. if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
  25. MetadataAwareAspectInstanceFactory factory =
  26. new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
  27. List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
  28. if (this.beanFactory.isSingleton(beanName)) {
  29. this.advisorsCache.put(beanName, classAdvisors);
  30. }
  31. else {
  32. this.aspectFactoryCache.put(beanName, factory);
  33. }
  34. advisors.addAll(classAdvisors);
  35. }
  36. else {
  37. // Per target or per this.
  38. if (this.beanFactory.isSingleton(beanName)) {
  39. throw new IllegalArgumentException("Bean with name '" + beanName +
  40. "' is a singleton, but aspect instantiation model is not singleton");
  41. }
  42. MetadataAwareAspectInstanceFactory factory =
  43. new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
  44. this.aspectFactoryCache.put(beanName, factory);
  45. advisors.addAll(this.advisorFactory.getAdvisors(factory));
  46. }
  47. }
  48. }
  49. this.aspectBeanNames = aspectNames;
  50. return advisors;
  51. }
  52. }
  53. }
  54. if (aspectNames.isEmpty()) {
  55. return Collections.emptyList();
  56. }
  57. List<Advisor> advisors = new ArrayList<>();
  58. for (String aspectName : aspectNames) {
  59. List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
  60. if (cachedAdvisors != null) {
  61. advisors.addAll(cachedAdvisors);
  62. }
  63. else {
  64. MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
  65. advisors.addAll(this.advisorFactory.getAdvisors(factory));
  66. }
  67. }
  68. return advisors;
  69. }

通过断点调试发现

  1. List<String> aspectNames = this.aspectBeanNames;

aspectNames已经有值了,怎么会这样,肯定什么地方先放进去了,做了缓存,也就是在执行

  1. initializeBean(beanName, exposedObject, mbd);

里面的后置处理器的after方法之前就已经放进去了,那到底哪里放进去的呢,我打个断点在这里,调试发现,是在这一行代码进去的。

  1. @Override
  2. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  3. throws BeanCreationException {
  4. if (logger.isTraceEnabled()) {
  5. logger.trace("Creating instance of bean '" + beanName + "'");
  6. }
  7. RootBeanDefinition mbdToUse = mbd;
  8. // Make sure bean class is actually resolved at this point, and
  9. // clone the bean definition in case of a dynamically resolved Class
  10. // which cannot be stored in the shared merged bean definition.
  11. Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
  12. if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
  13. mbdToUse = new RootBeanDefinition(mbd);
  14. mbdToUse.setBeanClass(resolvedClass);
  15. }
  16. // Prepare method overrides.
  17. try {
  18. mbdToUse.prepareMethodOverrides();
  19. }
  20. catch (BeanDefinitionValidationException ex) {
  21. throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
  22. beanName, "Validation of method overrides failed", ex);
  23. }
  24. try {
  25. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  26. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  27. if (bean != null) {
  28. return bean;
  29. }
  30. }
  31. catch (Throwable ex) {
  32. throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
  33. "BeanPostProcessor before instantiation of bean failed", ex);
  34. }
  35. try {
  36. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  37. if (logger.isTraceEnabled()) {
  38. logger.trace("Finished creating instance of bean '" + beanName + "'");
  39. }
  40. return beanInstance;
  41. }
  42. catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
  43. // A previously detected exception with proper bean creation context already,
  44. // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
  45. throw ex;
  46. }
  47. catch (Throwable ex) {
  48. throw new BeanCreationException(
  49. mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
  50. }
  51. }

在创建对象之前的这一行代码里执行的

  1. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  2. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

我们点进去看看

  1. @Nullable
  2. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  3. Object bean = null;
  4. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  5. // Make sure bean class is actually resolved at this point.
  6. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  7. Class<?> targetType = determineTargetType(beanName, mbd);
  8. if (targetType != null) {
  9. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
  10. if (bean != null) {
  11. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  12. }
  13. }
  14. }
  15. mbd.beforeInstantiationResolved = (bean != null);
  16. }
  17. return bean;
  18. }
  1. @Nullable
  2. protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
  3. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  4. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  5. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  6. Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
  7. if (result != null) {
  8. return result;
  9. }
  10. }
  11. }
  12. return null;
  13. }

而我们的类:AbstractAutoProxyCreator刚好继承了InstantiationAwareBeanPostProcessor,所以满足条件,我们直接找他的

  1. @Override
  2. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
  3. Object cacheKey = getCacheKey(beanClass, beanName);
  4. if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
  5. if (this.advisedBeans.containsKey(cacheKey)) {
  6. return null;
  7. }
  8. if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return null;
  11. }
  12. }
  13. // Create proxy here if we have a custom TargetSource.
  14. // Suppresses unnecessary default instantiation of the target bean:
  15. // The TargetSource will handle target instances in a custom fashion.
  16. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  17. if (targetSource != null) {
  18. if (StringUtils.hasLength(beanName)) {
  19. this.targetSourcedBeans.add(beanName);
  20. }
  21. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  22. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
  23. this.proxyTypes.put(cacheKey, proxy.getClass());
  24. return proxy;
  25. }
  26. return null;
  27. }

终于看到代码了,经过调试代码发现,这里是不会创建代理的,创建代理是在初始化的后置处理器的After方法,所以targetSource是null,这个方法的关键点就是

  1. shouldSkip(beanClass, beanName)

我们进入去看看

  1. @Override
  2. protected boolean shouldSkip(Class<?> beanClass, String beanName) {
  3. // TODO: Consider optimization by caching the list of the aspect names
  4. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  5. for (Advisor advisor : candidateAdvisors) {
  6. if (advisor instanceof AspectJPointcutAdvisor &&
  7. ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
  8. return true;
  9. }
  10. }
  11. return super.shouldSkip(beanClass, beanName);
  12. }

看到了熟悉的代码

  1. List<Advisor> candidateAdvisors = findCandidateAdvisors();

跟踪进去看看

  1. @Override
  2. protected List<Advisor> findCandidateAdvisors() {
  3. // Add all the Spring advisors found according to superclass rules.
  4. List<Advisor> advisors = super.findCandidateAdvisors();
  5. // Build Advisors for all AspectJ aspects in the bean factory.
  6. if (this.aspectJAdvisorsBuilder != null) {
  7. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  8. }
  9. return advisors;
  10. }

调试发现 super.findCandidateAdvisors();找不到任何的对象(这里好像是给事务逻辑来用的,按下不提),我们直接看

  1. this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
  1. public List<Advisor> buildAspectJAdvisors() {
  2. List<String> aspectNames = this.aspectBeanNames;
  3. if (aspectNames == null) {
  4. synchronized (this) {
  5. aspectNames = this.aspectBeanNames;
  6. if (aspectNames == null) {
  7. List<Advisor> advisors = new ArrayList<>();
  8. aspectNames = new ArrayList<>();
  9. //1、获取所有bean的名称,这里进行了所有的扫描,所以效率会很低,怪不得要用缓存
  10. String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  11. this.beanFactory, Object.class, true, false);
  12. for (String beanName : beanNames) {
  13. if (!isEligibleBean(beanName)) {
  14. continue;
  15. }
  16. // We must be careful not to instantiate beans eagerly as in this case they
  17. // would be cached by the Spring container but would not have been weaved.
  18. Class<?> beanType = this.beanFactory.getType(beanName);
  19. if (beanType == null) {
  20. continue;
  21. }
  22. //2、判断是否是切面,也就是加了@Aspect注解的类
  23. if (this.advisorFactory.isAspect(beanType)) {
  24. aspectNames.add(beanName);
  25. AspectMetadata amd = new AspectMetadata(beanType, beanName);
  26. if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
  27. MetadataAwareAspectInstanceFactory factory =
  28. new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
  29. //3、获取增强器对象
  30. List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
  31. if (this.beanFactory.isSingleton(beanName)) {
  32. //4、放入缓存中
  33. this.advisorsCache.put(beanName, classAdvisors);
  34. }
  35. else {
  36. this.aspectFactoryCache.put(beanName, factory);
  37. }
  38. advisors.addAll(classAdvisors);
  39. }
  40. else {
  41. // Per target or per this.
  42. if (this.beanFactory.isSingleton(beanName)) {
  43. throw new IllegalArgumentException("Bean with name '" + beanName +
  44. "' is a singleton, but aspect instantiation model is not singleton");
  45. }
  46. MetadataAwareAspectInstanceFactory factory =
  47. new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
  48. this.aspectFactoryCache.put(beanName, factory);
  49. advisors.addAll(this.advisorFactory.getAdvisors(factory));
  50. }
  51. }
  52. }
  53. //5、对aspectBeanNames进行赋值,第二次在后置处理器那里进来后就不为空了。
  54. this.aspectBeanNames = aspectNames;
  55. return advisors;
  56. }
  57. }
  58. }
  59. if (aspectNames.isEmpty()) {
  60. return Collections.emptyList();
  61. }
  62. List<Advisor> advisors = new ArrayList<>();
  63. for (String aspectName : aspectNames) {
  64. List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
  65. if (cachedAdvisors != null) {
  66. advisors.addAll(cachedAdvisors);
  67. }
  68. else {
  69. MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
  70. advisors.addAll(this.advisorFactory.getAdvisors(factory));
  71. }
  72. }
  73. return advisors;
  74. }

这终于绕回去了,从后置处理器进来的地方,但是此时这里的aspectNames为null,所以会进入的if逻辑。我上面都有注释,大概的步骤是
1、获取所有bean的名称,这里进行了所有的扫描,所以效率会很低,怪不得要用缓存
2、判断是否是切面,也就是加了@Aspect注解的类
3、获取增强器对象
4、放入缓存中
5、对aspectBeanNames进行赋值,第二次在后置处理器那里进来后就不为空了。

我们先来看下步骤2怎么判断是否是切面,这里其实很简单,看代码可以知道

  1. @Override
  2. public boolean isAspect(Class<?> clazz) {
  3. return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
  4. }
  5. private boolean hasAspectAnnotation(Class<?> clazz) {
  6. return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
  7. }

就是去找是否有@Aspect注解。

然后我们再看看步骤3,如何去获取增强器对象。

  1. List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
  1. @Override
  2. public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
  3. Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
  4. String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
  5. validate(aspectClass);
  6. // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
  7. // so that it will only instantiate once.
  8. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
  9. new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
  10. List<Advisor> advisors = new ArrayList<>();
  11. for (Method method : getAdvisorMethods(aspectClass)) {
  12. // Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
  13. // to getAdvisor(...) to represent the "current position" in the declared methods list.
  14. // However, since Java 7 the "current position" is not valid since the JDK no longer
  15. // returns declared methods in the order in which they are declared in the source code.
  16. // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
  17. // discovered via reflection in order to support reliable advice ordering across JVM launches.
  18. // Specifically, a value of 0 aligns with the default value used in
  19. // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
  20. Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
  21. if (advisor != null) {
  22. advisors.add(advisor);
  23. }
  24. }
  25. // If it's a per target aspect, emit the dummy instantiating aspect.
  26. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
  27. Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
  28. advisors.add(0, instantiationAdvisor);
  29. }
  30. // Find introduction fields.
  31. for (Field field : aspectClass.getDeclaredFields()) {
  32. Advisor advisor = getDeclareParentsAdvisor(field);
  33. if (advisor != null) {
  34. advisors.add(advisor);
  35. }
  36. }
  37. return advisors;
  38. }

我们直接去看获取增强器的逻辑

  1. Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
  1. @Override
  2. @Nullable
  3. public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
  4. int declarationOrderInAspect, String aspectName) {
  5. validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
  6. AspectJExpressionPointcut expressionPointcut = getPointcut(
  7. candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
  8. if (expressionPointcut == null) {
  9. return null;
  10. }
  11. return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
  12. this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
  13. }

直接进入到return逻辑

  1. public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
  2. Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
  3. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
  4. this.declaredPointcut = declaredPointcut;
  5. this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
  6. this.methodName = aspectJAdviceMethod.getName();
  7. this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
  8. this.aspectJAdviceMethod = aspectJAdviceMethod;
  9. this.aspectJAdvisorFactory = aspectJAdvisorFactory;
  10. this.aspectInstanceFactory = aspectInstanceFactory;
  11. this.declarationOrder = declarationOrder;
  12. this.aspectName = aspectName;
  13. if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
  14. // Static part of the pointcut is a lazy type.
  15. Pointcut preInstantiationPointcut = Pointcuts.union(
  16. aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
  17. // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
  18. // If it's not a dynamic pointcut, it may be optimized out
  19. // by the Spring AOP infrastructure after the first evaluation.
  20. this.pointcut = new PerTargetInstantiationModelPointcut(
  21. this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
  22. this.lazy = true;
  23. }
  24. else {
  25. // A singleton aspect.
  26. this.pointcut = this.declaredPointcut;
  27. this.lazy = false;
  28. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
  29. }
  30. }

很明显,看到初始化的地方

  1. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
  1. private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
  2. Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
  3. this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
  4. return (advice != null ? advice : EMPTY_ADVICE);
  5. }
  1. @Override
  2. @Nullable
  3. public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
  4. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
  5. Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
  6. validate(candidateAspectClass);
  7. AspectJAnnotation<?> aspectJAnnotation =
  8. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
  9. if (aspectJAnnotation == null) {
  10. return null;
  11. }
  12. // If we get here, we know we have an AspectJ method.
  13. // Check that it's an AspectJ-annotated class
  14. if (!isAspect(candidateAspectClass)) {
  15. throw new AopConfigException("Advice must be declared inside an aspect type: " +
  16. "Offending method '" + candidateAdviceMethod + "' in class [" +
  17. candidateAspectClass.getName() + "]");
  18. }
  19. if (logger.isDebugEnabled()) {
  20. logger.debug("Found AspectJ method: " + candidateAdviceMethod);
  21. }
  22. AbstractAspectJAdvice springAdvice;
  23. switch (aspectJAnnotation.getAnnotationType()) {
  24. case AtPointcut:
  25. if (logger.isDebugEnabled()) {
  26. logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
  27. }
  28. return null;
  29. case AtAround:
  30. springAdvice = new AspectJAroundAdvice(
  31. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  32. break;
  33. case AtBefore:
  34. springAdvice = new AspectJMethodBeforeAdvice(
  35. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  36. break;
  37. case AtAfter:
  38. springAdvice = new AspectJAfterAdvice(
  39. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  40. break;
  41. case AtAfterReturning:
  42. springAdvice = new AspectJAfterReturningAdvice(
  43. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  44. AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
  45. if (StringUtils.hasText(afterReturningAnnotation.returning())) {
  46. springAdvice.setReturningName(afterReturningAnnotation.returning());
  47. }
  48. break;
  49. case AtAfterThrowing:
  50. springAdvice = new AspectJAfterThrowingAdvice(
  51. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  52. AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
  53. if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
  54. springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
  55. }
  56. break;
  57. default:
  58. throw new UnsupportedOperationException(
  59. "Unsupported advice type on method: " + candidateAdviceMethod);
  60. }
  61. // Now to configure the advice...
  62. springAdvice.setAspectName(aspectName);
  63. springAdvice.setDeclarationOrder(declarationOrder);
  64. String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
  65. if (argNames != null) {
  66. springAdvice.setArgumentNamesFromStringArray(argNames);
  67. }
  68. springAdvice.calculateArgumentBindings();
  69. return springAdvice;
  70. }

最终到了目的地:判断你是AtAround、AtBefore、AtAfter、AtAfterReturning还是AtAfterThrowing,然后new对应的对象。

最后这一套操作昨晚后,我们的后置处理器就可以直接获得一批增强器(顾问advisor)了,可以安心的去对这些advisor生成代理对象了。

注:理论上是得先看上面的代码,再看后置处理器的代码的,我的流程是有问题的,不过跟踪源码本来就是连蒙带猜,没毛病!

然后接下来就是去创建代理了,我们点进去看下

  1. /**
  2. * Create an AOP proxy for the given bean.
  3. * @param beanClass the class of the bean
  4. * @param beanName the name of the bean
  5. * @param specificInterceptors the set of interceptors that is
  6. * specific to this bean (may be empty, but not null)
  7. * @param targetSource the TargetSource for the proxy,
  8. * already pre-configured to access the bean
  9. * @return the AOP proxy for the bean
  10. * @see #buildAdvisors
  11. */
  12. protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
  13. @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  14. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
  15. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  16. }
  17. ProxyFactory proxyFactory = new ProxyFactory();
  18. proxyFactory.copyFrom(this);
  19. if (!proxyFactory.isProxyTargetClass()) {
  20. if (shouldProxyTargetClass(beanClass, beanName)) {
  21. proxyFactory.setProxyTargetClass(true);
  22. }
  23. else {
  24. evaluateProxyInterfaces(beanClass, proxyFactory);
  25. }
  26. }
  27. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  28. proxyFactory.addAdvisors(advisors);
  29. proxyFactory.setTargetSource(targetSource);
  30. customizeProxyFactory(proxyFactory);
  31. proxyFactory.setFrozen(this.freezeProxy);
  32. if (advisorsPreFiltered()) {
  33. proxyFactory.setPreFiltered(true);
  34. }
  35. return proxyFactory.getProxy(getProxyClassLoader());
  36. }

这个按字面意思直接看最后

  1. /**
  2. * Create a new proxy according to the settings in this factory.
  3. * <p>Can be called repeatedly. Effect will vary if we've added
  4. * or removed interfaces. Can add and remove interceptors.
  5. * <p>Uses the given class loader (if necessary for proxy creation).
  6. * @param classLoader the class loader to create the proxy with
  7. * (or {@code null} for the low-level proxy facility's default)
  8. * @return the proxy object
  9. */
  10. public Object getProxy(@Nullable ClassLoader classLoader) {
  11. return createAopProxy().getProxy(classLoader);
  12. }

我们来看看createAopProxy()方法,看看是用什么来创建代理,我们知道创建动态代理无非就两样,一个是JDK自带的,一个是CGLIB,如果被代理的类有实现接口,通常永辉jdk自带的,否则会用cglib,我们点进去看看。

  1. /**
  2. * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
  3. * create an AOP proxy with {@code this} as an argument.
  4. */
  5. protected final synchronized AopProxy createAopProxy() {
  6. if (!this.active) {
  7. activate();
  8. }
  9. return getAopProxyFactory().createAopProxy(this);
  10. }
  1. @Override
  2. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  3. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  4. Class<?> targetClass = config.getTargetClass();
  5. if (targetClass == null) {
  6. throw new AopConfigException("TargetSource cannot determine target class: " +
  7. "Either an interface or a target is required for proxy creation.");
  8. }
  9. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
  10. return new JdkDynamicAopProxy(config);
  11. }
  12. return new ObjenesisCglibAopProxy(config);
  13. }
  14. else {
  15. return new JdkDynamicAopProxy(config);
  16. }
  17. }

对头,如果目标类是接口,则用JdkDynamicAopProxy,否则用ObjenesisCglibAopProxy,跟预想中的一样。

如果是jdk

  1. @Override
  2. public Object getProxy(@Nullable ClassLoader classLoader) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  5. }
  6. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  7. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  8. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  9. }

如果是cglib

  1. @Override
  2. public Object getProxy(@Nullable ClassLoader classLoader) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
  5. }
  6. try {
  7. Class<?> rootClass = this.advised.getTargetClass();
  8. Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
  9. Class<?> proxySuperClass = rootClass;
  10. if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
  11. proxySuperClass = rootClass.getSuperclass();
  12. Class<?>[] additionalInterfaces = rootClass.getInterfaces();
  13. for (Class<?> additionalInterface : additionalInterfaces) {
  14. this.advised.addInterface(additionalInterface);
  15. }
  16. }
  17. // Validate the class, writing log messages as necessary.
  18. validateClassIfNecessary(proxySuperClass, classLoader);
  19. // Configure CGLIB Enhancer...
  20. Enhancer enhancer = createEnhancer();
  21. if (classLoader != null) {
  22. enhancer.setClassLoader(classLoader);
  23. if (classLoader instanceof SmartClassLoader &&
  24. ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
  25. enhancer.setUseCache(false);
  26. }
  27. }
  28. enhancer.setSuperclass(proxySuperClass);
  29. enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
  30. enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
  31. enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
  32. Callback[] callbacks = getCallbacks(rootClass);
  33. Class<?>[] types = new Class<?>[callbacks.length];
  34. for (int x = 0; x < types.length; x++) {
  35. types[x] = callbacks[x].getClass();
  36. }
  37. // fixedInterceptorMap only populated at this point, after getCallbacks call above
  38. enhancer.setCallbackFilter(new ProxyCallbackFilter(
  39. this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
  40. enhancer.setCallbackTypes(types);
  41. // Generate the proxy class and create a proxy instance.
  42. return createProxyClassAndInstance(enhancer, callbacks);
  43. }
  44. catch (CodeGenerationException | IllegalArgumentException ex) {
  45. throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
  46. ": Common causes of this problem include using a final class or a non-visible class",
  47. ex);
  48. }
  49. catch (Throwable ex) {
  50. // TargetSource.getTarget() failed
  51. throw new AopConfigException("Unexpected AOP exception", ex);
  52. }
  53. }

到这里其实大概已经知道了AOP的实现原理,其它都是细节研究,比如怎么活动Advice啊。

一句话总结:Spring就是靠各种特殊的BeanPostProcessor来在实例化bean后对bean进行增强的。

一个简单的例子来探寻Spring实例化bean执行源码的主脉络(一):this()方法
一个简单的例子来探寻Spring实例化bean执行源码的主脉络(二):解析配置类
一个简单的例子来探寻Spring实例化bean执行源码的主脉络(三):扫包和实例化

 258

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2