Spring Boot启动过程

一个典型的SpringBoot应用入口

1
2
3
4
5
6
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@SpringBootApplication注解

1
2
3
4
5
6
7
8
9
10
11
12
13
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM,
        classes = AutoConfigurationExcludeFilter.class) })
@ConfigurationPropertiesScan
public @interface SpringBootApplication {
}

主要包括@SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan和@ConfigurationPropertiesScan。要注解发挥作用要先启动。

SpringBoot 启动过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SpringApplication {
  public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
  private List<ApplicationContextInitializer<?>> initializers;
  private List<ApplicationListener<?>> listeners;
  private Set<Class<?>> primarySources;

  public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
  }

  public static ConfigurableApplicationContext run(Class<?> primarySource,
      String... args) {
    return run(new Class<?>[] { primarySource }, args);
  }
}

用户的Application.class会作为primarySource,存到primarySources数组. 后面prepareContext的getAllSources和load会用到。

new的过程 * 推断application类型 * setInitializers * setListeners * 推断application

推断application类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public enum WebApplicationType {
  private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
      "org.springframework.web.context.ConfigurableWebApplicationContext" };

  private static final String WEBMVC_INDICATOR_CLASS = "org.springframework."
      + "web.servlet.DispatcherServlet";

  private static final String WEBFLUX_INDICATOR_CLASS = "org."
      + "springframework.web.reactive.DispatcherHandler";

  static WebApplicationType deduceFromClasspath() {
    if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
        && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
        && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
      return WebApplicationType.REACTIVE;
    }
    for (String className : SERVLET_INDICATOR_CLASSES) {
      if (!ClassUtils.isPresent(className, null)) {
        return WebApplicationType.NONE;
      }
    }
    return WebApplicationType.SERVLET;
  }
}

最后返回WebApplicationType.SERVLET

setInitializers和setListeners

这两个是类似的,调用getSpringFactoriesInstances,将结果分别放到SpringApplication数组initializers和listeners.

1
2
3
4
5
6
7
8
9
10
11
12
13
class SpringApplication {
  private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = getClassLoader();
    // Use names and ensure unique to protect against duplicates
    Set<String> names = new LinkedHashSet<>(
        SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
        classLoader, args, names);
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package org.springframework.core.io.support;
public final class SpringFactoriesLoader {
  public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
  private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    MultiValueMap<String, String> result = cache.get(classLoader);
    if (result != null) {
      return result;
    }

    try {
      Enumeration<URL> urls = (classLoader != null ?
          classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
          ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
      result = new LinkedMultiValueMap<>();
      while (urls.hasMoreElements()) {
        URL url = urls.nextElement();
        UrlResource resource = new UrlResource(url);
        Properties properties = PropertiesLoaderUtils.loadProperties(resource);
        for (Map.Entry<?, ?> entry : properties.entrySet()) {
          String factoryTypeName = ((String) entry.getKey()).trim();
          for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
            result.add(factoryTypeName, factoryImplementationName.trim());
          }
        }
      }
      cache.put(classLoader, result);
      return result;
    }
    catch (IOException ex) {
      throw new IllegalArgumentException("Unable to load factories from location [" +
          FACTORIES_RESOURCE_LOCATION + "]", ex);
    }
  }
}

加载spring-boot/src/resources/META-INFO/spring.factories

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=</span>
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,</span>
org.springframework.boot.context.ContextIdApplicationContextInitializer,</span>
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,</span>
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=</span>
org.springframework.boot.ClearCachesApplicationListener,</span>
org.springframework.boot.builder.ParentContextCloserApplicationListener,</span>
org.springframework.boot.context.FileEncodingApplicationListener,</span>
org.springframework.boot.context.config.AnsiOutputApplicationListener,</span>
org.springframework.boot.context.config.ConfigFileApplicationListener,</span>
org.springframework.boot.context.config.DelegatingApplicationListener,</span>
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,</span>
org.springframework.boot.context.logging.LoggingApplicationListener,</span>
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

使用classLoader加载类并初始化并返回数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class SpringApplication {
  private <T> List<T> createSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
      Set<String> names) {
    List<T> instances = new ArrayList<>(names.size());
    for (String name : names) {
      try {
        Class<?> instanceClass = ClassUtils.forName(name, classLoader);
        Assert.isAssignable(type, instanceClass);
        Constructor<?> constructor = instanceClass
            .getDeclaredConstructor(parameterTypes);
        // BeanUtils.instantiateClass使用反射返回一个实例
        T instance = (T) BeanUtils.instantiateClass(constructor, args);
        instances.add(instance);
      }
      catch (Throwable ex) {
        throw new IllegalArgumentException(
            "Cannot instantiate " + type + " : " + name, ex);
      }
    }
    return instances;
  }
}

找到定义main方法的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class SpringApplication {
  private Class<?> deduceMainApplicationClass() {
    try {
      StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
      for (StackTraceElement stackTraceElement : stackTrace) {
        if ("main".equals(stackTraceElement.getMethodName())) {
          return Class.forName(stackTraceElement.getClassName());
        }
      }
    }
    catch (ClassNotFoundException ex) {
      // Swallow and continue
    }
    return null;
  }
}

run方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class SpringApplication {
  public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
          args);
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
          applicationArguments);
      configureIgnoreBeanInfo(environment);
      Banner printedBanner = printBanner(environment);
      context = createApplicationContext();
      exceptionReporters = getSpringFactoriesInstances(
          SpringBootExceptionReporter.class,
          new Class[] { ConfigurableApplicationContext.class }, context);
      prepareContext(context, environment, listeners, applicationArguments,
          printedBanner);
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
      if (this.logStartupInfo) {
        new StartupInfoLogger(this.mainApplicationClass)
            .logStarted(getApplicationLog(), stopWatch);
      }
      listeners.started(context);
      callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
    }

    try {
      listeners.running(context);
    }
    catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
    }
    return context;
  }
}

run方法的状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface SpringApplicationRunListener {
  default void starting() {
  }
  default void environmentPrepared(ConfigurableEnvironment environment) {
  }
  default void contextPrepared(ConfigurableApplicationContext context) {
  }
  default void contextLoaded(ConfigurableApplicationContext context) {
  }
  default void started(ConfigurableApplicationContext context) {
  }
  default void running(ConfigurableApplicationContext context) {
  }
  default void failed(ConfigurableApplicationContext context, Throwable exception) {
  }
}

createApplicationContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class SpringApplication {
  public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
  protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
      try {
        switch (this.webApplicationType) {
        case SERVLET:
          contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
          break;
        case REACTIVE:
          contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
          break;
        default:
          contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
        }
      }
      catch (ClassNotFoundException ex) {
        throw new IllegalStateException(
            "Unable create a default ApplicationContext, "
                + "please specify an ApplicationContextClass",
            ex);
      }
    }
    // BeanUtils.instantiateClass使用反射,使用无参数构造器返回一个实例
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
  }
}

返回DEFAULTSERVLETWEBCONTEXTCLASS的实例.

prepareContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
class SpringApplication {
  private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);
    postProcessApplicationContext(context);
    // 遍历每个初始化器,对调用对应的initialize方法. initializer.initialize(context);
    applyInitializers(context);
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
      beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    // allowBeanDefinitionOverriding默认是false,不允许同名的bean,不能覆盖
    if (beanFactory instanceof DefaultListableBeanFactory) {
      ((DefaultListableBeanFactory) beanFactory)
          .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    // 默认为false
    if (this.lazyInitialization) {
      context.addBeanFactoryPostProcessor(
          new LazyInitializationBeanFactoryPostProcessor());
    }
    // Load the sources, 一般情况只有用户的Application.class
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    // 看load方法,Application.class是加载bean的入口
    load(context, sources.toArray(new Object[0]));
    listeners.contextLoaded(context);
  }

  // Load beans into the application context.
  protected void load(ApplicationContext context, Object[] sources) {
    if (logger.isDebugEnabled()) {
      logger.debug(
          "Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
    }
    BeanDefinitionLoader loader = createBeanDefinitionLoader(
        getBeanDefinitionRegistry(context), sources);
    if (this.beanNameGenerator != null) {
      loader.setBeanNameGenerator(this.beanNameGenerator);
    }
    if (this.resourceLoader != null) {
      loader.setResourceLoader(this.resourceLoader);
    }
    if (this.environment != null) {
      loader.setEnvironment(this.environment);
    }
    loader.load();
  }

  private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
    if (context instanceof BeanDefinitionRegistry) {
      return (BeanDefinitionRegistry) context;
    }
    // true
    if (context instanceof AbstractApplicationContext) {
      return (BeanDefinitionRegistry) ((AbstractApplicationContext) context)
          .getBeanFactory();
    }
    throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
  }

  protected BeanDefinitionLoader createBeanDefinitionLoader(
      BeanDefinitionRegistry registry, Object[] sources) {
    return new BeanDefinitionLoader(registry, sources);
  }
}

class BeanDefinitionLoader {
  private final AnnotatedBeanDefinitionReader annotatedReader;

  private int load(Object source) {
    Assert.notNull(source, "Source must not be null");
    if (source instanceof Class<?>) {
      return load((Class<?>) source);
    }
    // ...
  }

  private int load(Class<?> source) {
    if (isComponent(source)) {
      // Register one or more annotated classes to be processed.
      this.annotatedReader.register(source);
      return 1;
    }
    return 0;
  }
}

refreshContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class SpringApplication {
  protected void refresh(ApplicationContext applicationContext) {
    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    ((AbstractApplicationContext) applicationContext).refresh();
  }
}

package org.springframework.context.support;
public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext {
  public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();
      // Tell the subclass to refresh the internal bean factory.
      // 对于传统的xml配置应用,配置文件变成bean definition,注册到beanRegistory. 一个beanName->beanDefination的hashmap,
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // Prepare the bean factory for use in this context.
      // 设置BeanFactory的类加载器
      prepareBeanFactory(beanFactory);

      try {
        // Allows post-processing of the bean factory in context subclasses.
        // 对于注解类型的web应用, postProcessBeanFactory scan&read,并将文件级别的注解放到一个数组,只是简单提取不会做具体处理。reader会注册factory post processor事件,处理具体的注解。
        postProcessBeanFactory(beanFactory);
        // Invoke factory processors registered as beans in the context.
        // 处理@Configuration和@Autowired
        invokeBeanFactoryPostProcessors(beanFactory);
        // Register bean processors that intercept bean creation.
        registerBeanPostProcessors(beanFactory);
        // Initialize message source for this context.
        initMessageSource();
        // Initialize event multicaster for this context.
        initApplicationEventMulticaster();
        // Initialize other special beans in specific context subclasses.
        onRefresh();
        // Check for listener beans and register them.
        registerListeners();
        // Instantiate all remaining (non-lazy-init) singletons.
        // 初始化所有singleton beans
        finishBeanFactoryInitialization(beanFactory);
        // Last step: publish corresponding event.
        finishRefresh();
      }

      catch (BeansException ex) {
        if (logger.isWarnEnabled()) {
          logger.warn("Exception encountered during context initialization - " +
              "cancelling refresh attempt: " + ex);
        }
        // Destroy already created singletons to avoid dangling resources.
        destroyBeans();
        // Reset 'active' flag.
        cancelRefresh(ex);
        // Propagate exception to caller.
        throw ex;
      }

      finally {
        // Reset common introspection caches in Spring's core, since we
        // might not ever need metadata for singleton beans anymore...
        resetCommonCaches();
      }
    }
  }
}

refreshContext - postProcessBeanFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.springframework.boot.web.servlet.context;
public class AnnotationConfigServletWebServerApplicationContext
    extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
  private final AnnotatedBeanDefinitionReader reader;
  private final ClassPathBeanDefinitionScanner scanner;
  public AnnotationConfigServletWebServerApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
  }
  protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.postProcessBeanFactory(beanFactory);
    if (this.basePackages != null && this.basePackages.length > 0) {
      this.scanner.scan(this.basePackages);
    }
    if (!this.annotatedClasses.isEmpty()) {
      this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
    }
  }
}

spring boot在postProcessBeanFactory中扫描并读取classes

refreshContext - postProcessBeanFactory - scan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package org.springframework.context.annotation;
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
  private boolean includeAnnotationConfig = true;
  public int scan(String... basePackages) {
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

    doScan(basePackages);

    // Register annotation config processors, if necessary.
    if (this.includeAnnotationConfig) {
      AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
  }

  // Perform a scan within the specified base packages,
  // returning the registered bean definitions.
  // This method does not register an annotation config processor
  protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
      // 调用scanCandidateComponents
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      for (BeanDefinition candidate : candidates) {
        // new AnnotationScopeMetadataResolver()
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
        candidate.setScope(scopeMetadata.getScopeName());
        String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
        if (candidate instanceof AbstractBeanDefinition) {
          postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
        }
        if (candidate instanceof AnnotatedBeanDefinition) {
          AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
        }
        if (checkCandidate(beanName, candidate)) {
          BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
          definitionHolder =
              AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
          beanDefinitions.add(definitionHolder);
          registerBeanDefinition(definitionHolder, this.registry);
        }
      }
    }
    return beanDefinitions;
  }
}

package org.springframework.context.annotation;
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
  static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
  private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
        resolveBasePackage(basePackage) + '/' + this.resourcePattern;
    // getResourcePatternResolver返回PathMatchingResourcePatternResolver
    Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    boolean traceEnabled = logger.isTraceEnabled();
    boolean debugEnabled = logger.isDebugEnabled();
    for (Resource resource : resources) {
      if (resource.isReadable()) {
        // getMetadataReaderFactory返回CachingMetadataReaderFactory
        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
        if (isCandidateComponent(metadataReader)) {
          ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
          sbd.setResource(resource);
          sbd.setSource(resource);
          if (isCandidateComponent(sbd)) {
            if (debugEnabled) {
              logger.debug("Identified candidate component class: " + resource);
            }
            candidates.add(sbd);
          }
        }
      }
    }
    return candidates;
  }
}

package org.springframework.core.io.support;
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
  public Resource[] getResources(String locationPattern) throws IOException {
    Assert.notNull(locationPattern, "Location pattern must not be null");
    if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
      // a class path resource (multiple resources for same name possible)
      if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
        // a class path resource pattern
        return findPathMatchingResources(locationPattern);
      }
      else {
        // all class path resources with the given name
        return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
      }
    }
    // tomcat
  }

  protected Resource[] findAllClassPathResources(String location) throws IOException {
    String path = location;
    if (path.startsWith("/")) {
      path = path.substring(1);
    }
    Set<Resource> result = doFindAllClassPathResources(path);
    return result.toArray(new Resource[0]);
  }

  protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
    Set<Resource> result = new LinkedHashSet<>(16);
    ClassLoader cl = getClassLoader();
    Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
    while (resourceUrls.hasMoreElements()) {
      URL url = resourceUrls.nextElement();
      result.add(convertClassLoaderURL(url));
    }
    if ("".equals(path)) {
      // The above result is likely to be incomplete, i.e. only containing file system references.
      // We need to have pointers to each of the jar files on the classpath as well...
      addAllClassLoaderJarRoots(cl, result);
    }
    return result;
  }
}

package org.springframework.core.type.classreading;
public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
  public MetadataReader getMetadataReader(Resource resource) throws IOException {
    if (this.metadataReaderCache instanceof ConcurrentMap) {
      // No synchronization necessary...
      MetadataReader metadataReader = this.metadataReaderCache.get(resource);
      if (metadataReader == null) {
        metadataReader = super.getMetadataReader(resource);
        this.metadataReaderCache.put(resource, metadataReader);
      }
      return metadataReader;
    }
    else if (this.metadataReaderCache != null) {
      synchronized (this.metadataReaderCache) {
        MetadataReader metadataReader = this.metadataReaderCache.get(resource);
        if (metadataReader == null) {
          metadataReader = super.getMetadataReader(resource);
          this.metadataReaderCache.put(resource, metadataReader);
        }
        return metadataReader;
      }
    }
    else {
      return super.getMetadataReader(resource);
    }
  }
}

package org.springframework.core.type.classreading;
public class SimpleMetadataReaderFactory implements MetadataReaderFactory {
  public MetadataReader getMetadataReader(Resource resource) throws IOException {
    return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
  }
}

package org.springframework.core.type.classreading;
final class SimpleMetadataReader implements MetadataReader {
  SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
    InputStream is = new BufferedInputStream(resource.getInputStream());
    ClassReader classReader;
    try {
      classReader = new ClassReader(is);
    }
    catch (IllegalArgumentException ex) {
      throw new NestedIOException("ASM ClassReader failed to parse class file - " +
          "probably due to a new Java class file version that isn't supported yet: " + resource, ex);
    }
    finally {
      is.close();
    }

    AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
    classReader.accept(visitor, ClassReader.SKIP_DEBUG);

    this.annotationMetadata = visitor;
    // (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
    this.classMetadata = visitor;
    this.resource = resource;
  }
}

总结一下 * ClassPathBeanDefinitionScanner.doScan,调用findCandidateComponents(basePackage) * findCandidateComponents实际调用ClassPathScanningCandidateComponentProvider.scanCandidateComponents * 使用PathMatchingResourcePatternResolver.getResources(packageSearchPath),得到Resource[] * 遍历Resource[], 使用CachingMetadataReaderFactory.getMetadataReader(resource). * 首先会尝试在缓存(concurrentHashMap)中找, 得到metadataReader. * 缓存没有则调用SimpleMetadataReaderFactory.getMetadataReader(resource) * 调用SimpleMetadataReader,读取resource InputStream,类加载。 * 使用AnnotationMetadataReadingVisitor读取加载上一步的注解信息。 * metadataReader将resource转换成BeanDefinition * 遍历BeanDefinition[],解析BeanDefinition,得到BeanDefinitionHolder[]

读取注解, 并注册PostProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package org.springframework.context.annotation;
public class 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);
  }
}

package org.springframework.context.annotation;
public abstract class AnnotationConfigUtils {
  public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      BeanDefinitionRegistry registry, @Nullable Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
      if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
        beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
      }
      if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
      }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    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));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition();
      try {
        def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
            AnnotationConfigUtils.class.getClassLoader()));
      }
      catch (ClassNotFoundException ex) {
        throw new IllegalStateException(
            "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
      }
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
  }
}

package org.springframework.context.annotation;
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
    PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
  public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    String[] candidateNames = registry.getBeanDefinitionNames();

    // 遍历所有bean,查找含有@Configuration注解的,添加到Candidates
    for (String beanName : candidateNames) {
      BeanDefinition beanDef = registry.getBeanDefinition(beanName);
      if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
        if (logger.isDebugEnabled()) {
          logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
        }
      }
      else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
      }
    }

    // Parse each @Configuration class
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
      parser.parse(candidates);
      parser.validate();
      //
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package org.springframework.context.annotation;
class ConfigurationClassParser {
  protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {
    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
      // Recursively process any member (nested) classes first
      processMemberClasses(configClass, sourceClass);
    }

    // Process any @PropertySource annotations

    // Process any @ComponentScan annotations
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
        !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
      for (AnnotationAttributes componentScan : componentScans) {
        // The config class is annotated with @ComponentScan -> perform the scan immediately
        Set<BeanDefinitionHolder> scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
        // Check the set of scanned definitions for any further config classes and parse recursively if needed
        for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
          BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
          if (bdCand == null) {
            bdCand = holder.getBeanDefinition();
          }
          if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
            parse(bdCand.getBeanClassName(), holder.getBeanName());
          }
        }
      }
    }

    // Process any @Import annotations
    // Process any @ImportResource annotations

    // Process individual @Bean methods
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // Process default methods on interfaces
    // Process superclass, if any
    // No superclass -> processing is complete
    return null;
  }
}

碰到@ComponentScan,会调用componentScanParser处理. 若果扫描出的bean定义是@Configuration,则递归调用parse方法

finishBeanFactoryInitialization

调用DefaultListableBeanFactory.preInstantiateSingletons()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
    }

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        if (isFactoryBean(beanName)) {
          Object bean = getBean(FACTORYBEANPREFIX + beanName);
          if (bean instanceof FactoryBean) {
            final FactoryBean<?> factory = (FactoryBean<?>) bean;
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
              isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                      ((SmartFactoryBean<?>) factory)::isEagerInit,
                  getAccessControlContext());
            }
            else {
              isEagerInit = (factory instanceof SmartFactoryBean &&
                  ((SmartFactoryBean<?>) factory).isEagerInit());
            }
            if (isEagerInit) {
              getBean(beanName);
            }
          }
        }
        else {
          getBean(beanName);
        }
      }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            smartSingleton.afterSingletonsInstantiated();
            return null;
          }, getAccessControlContext());
        }
        else {
          smartSingleton.afterSingletonsInstantiated();
        }
      }
    }
  }

遍历beanNames,调用getBean(beanName)。 结果放到一个hashmap, beanName bean实例

getSingleton调用DefaultSingletonBeanRegistry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

  protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
          ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
          if (singletonFactory != null) {
            singletonObject = singletonFactory.getObject();
            this.earlySingletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
          }
        }
      }
    }
    return singletonObject;
  }
使用earlySingletonObjects,避免循环依赖的死循环。

AOP

主要逻辑在AbstractAutoProxyCreator,通过beanPostProcessor的postProcessAfterInitialization方法,调用wrapIfNecessary.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
}

public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
}

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
  protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
    }
    return advisors.toArray();
  }

  protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();
  }
}

public class BeanFactoryAdvisorRetrievalHelper {
  /**
   * Find all eligible Advisor beans in the current bean factory,
   * ignoring FactoryBeans and excluding beans that are currently in creation.
   * @return the list of {@link org.springframework.aop.Advisor} beans
   * @see #isEligibleBean
   */
  public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the auto-proxy creator apply to them!
      advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
          this.beanFactory, Advisor.class, true, false);
      this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
      return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
      if (isEligibleBean(name)) {
        if (this.beanFactory.isCurrentlyInCreation(name)) {
          // Skipping currently created advisor
        }
        else {
          advisors.add(this.beanFactory.getBean(name, Advisor.class));
        }
      }
    }
    return advisors;
  }
}

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
    implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
  /**
   * Create a proxy with the configured interceptors if the bean is
   * identified as one to proxy by the subclass.
   * @see #getAdvicesAndAdvisorsForBean
   */
  @Override
  public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
        return wrapIfNecessary(bean, beanName, cacheKey);
      }
    }
    return bean;
  }

  /**
   * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
   * @param bean the raw bean instance
   * @param beanName the name of the bean
   * @param cacheKey the cache key for metadata access
   * @return a proxy wrapping the bean, or the raw bean instance as-is
   */
  protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && 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;
  }

  protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
      @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
        proxyFactory.setProxyTargetClass(true);
      }
      else {
        evaluateProxyInterfaces(beanClass, proxyFactory);
      }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
    }

    return proxyFactory.getProxy(getProxyClassLoader());
  }
}

AspectJProxyFactory继承ProxyCreatorSupport; ProxyCreatorSupport会实例化DefaultAopProxyFactory; DefaultAopProxyFactory会为接口使用JDK代理,否则使用cglib

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
  @Override
  public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
        throw new AopConfigException("TargetSource cannot determine target class: " +
            "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
        return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
    }
    else {
      return new JdkDynamicAopProxy(config);
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
 * Base class for {@link BeanPostProcessor} implementations that apply a
 * Spring AOP {@link Advisor} to specific beans.
 */
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (this.advisor == null || bean instanceof AopInfrastructureBean) {
      // Ignore AOP infrastructure such as scoped proxies.
      return bean;
    }

    if (bean instanceof Advised) {
      Advised advised = (Advised) bean;
      if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
        // Add our local Advisor to the existing proxy's Advisor chain...
        if (this.beforeExistingAdvisors) {
          advised.addAdvisor(0, this.advisor);
        }
        else {
          advised.addAdvisor(this.advisor);
        }
        return bean;
      }
    }

    if (isEligible(bean, beanName)) {
      ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
      if (!proxyFactory.isProxyTargetClass()) {
        evaluateProxyInterfaces(bean.getClass(), proxyFactory);
      }
      proxyFactory.addAdvisor(this.advisor);
      customizeProxyFactory(proxyFactory);
      return proxyFactory.getProxy(getProxyClassLoader());
    }

    // No proxy needed.
    return bean;
  }

  /**
   * Check whether the given class is eligible for advising with this
   * post-processor's {@link Advisor}.
   * <p>Implements caching of {@code canApply} results per bean target class.
   * @param targetClass the class to check against
   * @see AopUtils#canApply(Advisor, Class)
   */
  protected boolean isEligible(Class<?> targetClass) {
    Boolean eligible = this.eligibleBeans.get(targetClass);
    if (eligible != null) {
      return eligible;
    }
    if (this.advisor == null) {
      return false;
    }
    eligible = AopUtils.canApply(this.advisor, targetClass);
    this.eligibleBeans.put(targetClass, eligible);
    return eligible;
  }
}

AopUtils.canApply判断与execution是否匹配。

mini componentScan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.demo.componentscan;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class Demo {
  public static void main(String[] args) throws Exception {
    Demo demo = new Demo();
    demo.doScan();
  }

  public void doScan() throws ClassNotFoundException {
    ClassLoader classLoader = getClass().getClassLoader();
    String packageName = getClass().getPackage().getName(); // com.demo.scan
    String packagePath  = packageName.replace('.', '/');    // com/demo/scan
    URL url = classLoader.getResource(packagePath);
    System.out.println(url);
      File folder = new File(url.getPath());
      File[] files = folder.listFiles();            // 编译后的文件 *.class

      List<Class<?>> classList = new ArrayList<Class<?>>();
      for (int i=0;i<files.length;i++) {
        int index = files[i].getName().indexOf(".");        // Demo.class, index=4
        String className = files[i].getName().substring(0, index);  // Demo.class => Demo
        String classNamePath = packageName + "." + className;     // com.demo.componentscan.Demo
        Class<?> klass = Class.forName(classNamePath);
      }
  }
}
  • ClassLoader.getResource(packagePath). 返回url是编译后的文件路径
  • 使用File api读取URL,得到File[]。编译后的class文件
  • 提取File的文件名
  • 使用反射Class.forName(classNamePath)