文章目录
大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。
孙哥链接:孙哥个人主页
作者简介:一个颜值99分,只比孙哥差一点的程序员
本专栏简介:话不多说,让我们一起干翻SpringSecurity6本文章简介:话不多说,让我们讲清楚SpringSecurity6中为什么在引入SpringSecurity之后所有的请求都需要先做登录认证才可以进行访问呢
- public static void main(String[] args) {
- SpringApplication.run(AlibabaApplication.class, args);
- }
然后走到了一个run方法:
- public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
- return new SpringApplication(primarySources).run(args);
- }
查看这里边的构造器方法:
- public SpringApplication(Class>... primarySources) {
- this(null, 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();
- this.bootstrapRegistryInitializers = new ArrayList<>(
- getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
- setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
- setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
- this.mainApplicationClass = deduceMainApplicationClass();
- }
随后,我们查看具体的run方法:
- public ConfigurableApplicationContext run(String... args) {
- long startTime = System.nanoTime();
- DefaultBootstrapContext bootstrapContext = createBootstrapContext();
- ConfigurableApplicationContext context = null;
- configureHeadlessProperty();
- SpringApplicationRunListeners listeners = getRunListeners(args);
- listeners.starting(bootstrapContext, this.mainApplicationClass);
- try {
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
- ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
- Banner printedBanner = printBanner(environment);
- context = createApplicationContext();
- context.setApplicationStartup(this.applicationStartup);
- //准备解析工作
- prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
- //真正的解析工作
- refreshContext(context);
- afterRefresh(context, applicationArguments);
- Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
- if (this.logStartupInfo) {
- new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
- }
- listeners.started(context, timeTakenToStartup);
- callRunners(context, applicationArguments);
- }
- catch (Throwable ex) {
- if (ex instanceof AbandonedRunException) {
- throw ex;
- }
- handleRunFailure(context, ex, listeners);
- throw new IllegalStateException(ex);
- }
- try {
- if (context.isRunning()) {
- Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
- listeners.ready(context, timeTakenToReady);
- }
- }
- catch (Throwable ex) {
- if (ex instanceof AbandonedRunException) {
- throw ex;
- }
- handleRunFailure(context, ex, null);
- throw new IllegalStateException(ex);
- }
- return context;
- }
我们查看准备工作:
- private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
- ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments, Banner printedBanner) {
- context.setEnvironment(environment);
- postProcessApplicationContext(context);
- addAotGeneratedInitializerIfNecessary(this.initializers);
- applyInitializers(context);
- listeners.contextPrepared(context);
- bootstrapContext.close(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);
- }
- if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
- autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
- if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
- listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
- }
- }
- if (this.lazyInitialization) {
- context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
- }
- context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
- if (!AotDetector.useGeneratedArtifacts()) {
- // Load the sources
- Set
- Assert.notEmpty(sources, "Sources must not be empty");
- load(context, sources.toArray(new Object[0]));
- }
- listeners.contextLoaded(context);
- }
getAllSources获取入口类的信息。放到sources这个Set集合里边,然后去做load,我们查看load方法。
- 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();
- }
-
- void load() {
- for (Object source : this.sources) {
- load(source);
- }
- }
-
- private void load(Object source) {
- Assert.notNull(source, "Source must not be null");
- if (source instanceof Class> clazz) {
- load(clazz);
- return;
- }
- if (source instanceof Resource resource) {
- load(resource);
- return;
- }
- if (source instanceof Package pack) {
- load(pack);
- return;
- }
- if (source instanceof CharSequence sequence) {
- load(sequence);
- return;
- }
- throw new IllegalArgumentException("Invalid source type " + source.getClass());
- }
-
- private void load(Class> source) {
- if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
- // Any GroovyLoaders added in beans{} DSL can contribute beans here
- GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
- ((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());
- }
- if (isEligible(source)) {
- this.annotatedReader.register(source);
- }
- }
到这里完成了一个重要的工作:读取入口类中重要的信息,包括注解包括入口类本身。将入口类中的注解注册到注解解读器annotationreader当中。
真正解析Bean的工作是从refreshContext当中进行的。
- private void refreshContext(ConfigurableApplicationContext context) {
- if (this.registerShutdownHook) {
- shutdownHook.registerApplicationContext(context);
- }
- refresh(context);
- }
-
- protected void refresh(ConfigurableApplicationContext applicationContext) {
- applicationContext.refresh();
- }
最后跑到了一个applicationContext的refresh方法当中。
- @Override
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
- StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
-
- // Prepare this context for refreshing.
- prepareRefresh();
-
- // Tell the subclass to refresh the internal bean factory.
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
-
- // Prepare the bean factory for use in this context.
- prepareBeanFactory(beanFactory);
-
- try {
- // Allows post-processing of the bean factory in context subclasses.
- postProcessBeanFactory(beanFactory);
-
- StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
- // Invoke factory processors registered as beans in the context.
- invokeBeanFactoryPostProcessors(beanFactory);
-
- // Register bean processors that intercept bean creation.
- registerBeanPostProcessors(beanFactory);
- beanPostProcess.end();
-
- // 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.
- 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();
- contextRefresh.end();
- }
- }
- }
接下来会进行Bean处理的13方法,其中一个比较关键的方法:invokeBeanFactoryPostProcessors
- protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
-
- // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
- // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
- if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
- beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
- beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
- beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
- }
- }
这里边会对我们的入口类中的注解进行详细的解析和复杂调用。其中对这些注解进行解析的时候,要用到了这么一个类:AutoConfigurationImportSelector
我们可以从调用链路上去证明这件事情:
- "main@1" prio=5 tid=0x1 nid=NA runnable
- java.lang.Thread.State: RUNNABLE
- at org.springframework.boot.context.annotation.ImportCandidates.load(ImportCandidates.java:90)
- at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getCandidateConfigurations(AutoConfigurationImportSelector.java:180)
- at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:126)
- at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:430)
- at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:796)
- at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:726)
- at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:697)
- at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:182)
- at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:415)
- at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:287)
- at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:344)
- at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115)
- at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:779)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
- - locked <0x12a7> (a java.lang.Object)
- at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290)
- at com.dashu.AlibabaApplication.main(AlibabaApplication.java:10)
所以,这个在自动装配的过程当中,确实完成了SpringSecurity的自动加载和配置。