网站设计的目的和任务深圳建站哪家专业
news/
2025/9/22 16:32:56/
文章来源:
网站设计的目的和任务,深圳建站哪家专业,太原百度推广制作个性商城网站,番禺网站建设gzhchl目录 如何引入第三方库第三方库与当前项目Bean重复自定义自动配置类 自动配置类通常位于Spring Boot的自动配置模块中#xff0c;并且被标记为
Configuration类。这些类使用
Conditional注解来检查某些条件是否满足#xff0c;如果满足#xff0c;则创建和配置相关的bean。… 目录 如何引入第三方库第三方库与当前项目Bean重复自定义自动配置类 自动配置类通常位于Spring Boot的自动配置模块中并且被标记为
Configuration类。这些类使用
Conditional注解来检查某些条件是否满足如果满足则创建和配置相关的bean。这些条件可能包括检查类路径上是否存在特定的类、检查应用程序的属性设置、检查是否存在特定的bean等。 自动配置类还可用于自动配置各种常见的Spring组件和第三方库。这些自动配置类大大简化了应用程序的配置过程使得开发者可以更加专注于实现业务逻辑而不是花费大量时间在繁琐的配置上。
如何引入第三方库
看如下示例
package com.cys.spring.chapter16;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.GenericApplicationContext;public class TestAutoConfig {SuppressWarnings(all)public static void main(String[] args) {GenericApplicationContext context new GenericApplicationContext();context.registerBean(config, Config.class);context.registerBean(ConfigurationClassPostProcessor.class);context.refresh();for (String name : context.getBeanDefinitionNames()) {System.out.println(name);}System.out.println();System.out.println(context.getBean(Bean1.class));}Configuration // 本项目的配置类Import({AutoConfiguration1.class, AutoConfiguration2.class})static class Config {}Configuration // 第三方的配置类static class AutoConfiguration1 {Beanpublic Bean1 bean1() {return new Bean1(第三方);}}static class Bean1 {private String name;public Bean1() {}public Bean1(String name) {this.name name;}Overridepublic String toString() {return Bean1{ name name \ };}}Configuration // 第三方的配置类static class AutoConfiguration2 {Beanpublic Bean2 bean2() {return new Bean2();}}static class Bean2 {}
}运行
config
org.springframework.context.annotation.ConfigurationClassPostProcessor
com.cys.spring.chapter16.TestAutoConfig$AutoConfiguration1
bean1
com.cys.spring.chapter16.TestAutoConfig$AutoConfiguration2
bean2Bean1{name第三方}首先在我们当前应用的配置类Config中使用Import({AutoConfiguration1.class, AutoConfiguration2.class})将模拟出的第三方的配置类AutoConfiguration1和AutoConfiguration2导入到了我们自己的应用程序中接着就可以使用他们俩的配置类中创建的Bean。
接着我们优化一下不把导入的类名写死在代码而是配合ImportSelector将其写在配置文件中文件名需要是src/main/resources/META-INF/spring.factories
配置文件内容
com.cys.spring.chapter16.TestAutoConfig$MyImportSelector\
com.cys.spring.chapter16.TestAutoConfig.AutoConfiguration1,\
com.cys.spring.chapter16.TestAutoConfig.AutoConfiguration2然后修改测试类如下
Configuration // 本项目的配置类
Import(MyImportSelector.class)
// Import({AutoConfiguration1.class, AutoConfiguration2.class})
static class Config {
}/*** 创建一个ImportSelector返回配置文件的类名*/
static class MyImportSelector implements ImportSelector {Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {ListString names SpringFactoriesLoader.loadFactoryNames(MyImportSelector.class, null);return names.toArray(new String[0]);}
}这样也是没问题的。
第三方库与当前项目Bean重复
如果第三方库与当前项目Bean重复默认是引入的第三方的先创建然后自己程序的再创建且后创建的可以覆盖前面的。
可以设置为不允许覆盖就会有Bean重复的报错设置方法如下
setAllowBeanDefinitionOverriding(false);修改后如下
public static void main(String[] args) {GenericApplicationContext context new GenericApplicationContext();// 如果有同名的Bean是否允许覆盖context.getDefaultListableBeanFactory().setAllowBeanDefinitionOverriding(false);context.registerBean(config, Config.class);context.registerBean(ConfigurationClassPostProcessor.class);context.refresh();for (String name : context.getBeanDefinitionNames()) {System.out.println(name);}System.out.println();System.out.println(context.getBean(Bean1.class));}运行后报错
Exception in thread main org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name bean1 defined in com.cys.spring.chapter16.TestAutoConfig$Config: Cannot register bean definition [Root bean: class [null]; defined in com.cys.spring.chapter16.TestAutoConfig$Config] for bean bean1: There is already [Root bean: class [null]; defined in class path resource [com/cys/spring/chapter16/TestAutoConfig$AutoConfiguration1.class]] bound.意思就是无法注册TestAutoConfig C o n f i g 中的 b e a n 1 的 b e a n d e f i n i t i o n 因为在 T e s t A u t o C o n f i g Config中的bean1的 bean definition因为在TestAutoConfig Config中的bean1的beandefinition因为在TestAutoConfigAutoConfiguration1.class中已经存在。
实际生产中不建议这么做建议开启覆盖。
那么如果要调整注册 bean definition的顺序呢让自己程序的先注册第三方的后注册呢也可以但实际生产也不建议这么做。
真要修改的话可以创建ImportSelector时实现DeferredImportSelector达到延迟注册的目的。如下
static class MyImportSelector implements DeferredImportSelector {Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {ListString names SpringFactoriesLoader.loadFactoryNames(MyImportSelector.class, null);return names.toArray(new String[0]);}}自定义自动配置类
在Springboot中自动配置通常使用EnableAutoConfiguration。源码如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;Target({ElementType.TYPE})
Retention(RetentionPolicy.RUNTIME)
Documented
Inherited
AutoConfigurationPackage
Import({AutoConfigurationImportSelector.class})
public interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY spring.boot.enableautoconfiguration;Class?[] exclude() default {};String[] excludeName() default {};
}他也是使用了Import注解去找spring.fatories文件中找AutoConfigurationImportSelector的key。AutoConfigurationImportSelectory中也有个selectImports其源码如下
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {private static final AutoConfigurationImportSelector.AutoConfigurationEntry EMPTY_ENTRY new AutoConfigurationImportSelector.AutoConfigurationEntry();private static final String[] NO_IMPORTS new String[0];private static final Log logger LogFactory.getLog(AutoConfigurationImportSelector.class);private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE spring.autoconfigure.exclude;private ConfigurableListableBeanFactory beanFactory;private Environment environment;private ClassLoader beanClassLoader;private ResourceLoader resourceLoader;private AutoConfigurationImportSelector.ConfigurationClassFilter configurationClassFilter;public AutoConfigurationImportSelector() {}public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry this.getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}}
}主要方法getAutoConfigurationEntry
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return EMPTY_ENTRY;} else {AnnotationAttributes attributes this.getAttributes(annotationMetadata);ListString configurations this.getCandidateConfigurations(annotationMetadata, attributes);configurations this.removeDuplicates(configurations);SetString exclusions this.getExclusions(annotationMetadata, attributes);this.checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations this.getConfigurationClassFilter().filter(configurations);this.fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);}
}进入方法getCandidateConfigurations
protected ListString getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {ListString configurations SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());Assert.notEmpty(configurations, No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.);return configurations;
}他也是使用方法SpringFactoriesLoader.loadFactoryNames找配置类名称其中key是this.getSpringFactoriesLoaderFactoryClass()方法返回值
protected Class? getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;
}进入方法看到他最后找的类名为EnableAutoConfiguration的key。
根据这个我们在spring.factories中添加这个key:
com.cys.spring.chapter16.TestAutoConfig$MyImportSelector\
com.cys.spring.chapter16.TestAutoConfig.AutoConfiguration1,\
com.cys.spring.chapter16.TestAutoConfig.AutoConfiguration2org.springframework.boot.autoconfigure.EnableAutoConfiguration\
com.cys.spring.chapter16.TestAutoConfig.AutoConfiguration1,\
com.cys.spring.chapter16.TestAutoConfig.AutoConfiguration2并在配置类上加上EnableAutoConfiguration:
package com.cys.spring.chapter16;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.env.SimpleCommandLinePropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;import java.io.IOException;public class TestSelfAutoConfiguration {SuppressWarnings(all)public static void main(String[] args) throws IOException {AnnotationConfigServletWebServerApplicationContext context new AnnotationConfigServletWebServerApplicationContext();StandardEnvironment env new StandardEnvironment();env.getPropertySources().addLast(new SimpleCommandLinePropertySource(--spring.datasource.urljdbc:mysql://localhost:3306/test,--spring.datasource.usernameroot,--spring.datasource.passwordroot));context.setEnvironment(env);context.registerBean(config, Config.class);context.refresh();for (String name : context.getBeanDefinitionNames()) {String resourceDescription context.getBeanDefinition(name).getResourceDescription();if (resourceDescription ! null)System.out.println(name 来源: resourceDescription);}context.close();}Configuration // 本项目的配置类
// Import(MyImportSelector.class)
// Import(AutoConfigurationImportSelector.class)EnableAutoConfigurationstatic class Config {Beanpublic TomcatServletWebServerFactory tomcatServletWebServerFactory() {return new TomcatServletWebServerFactory();}}static class MyImportSelector implements DeferredImportSelector {Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return SpringFactoriesLoader.loadFactoryNames(MyImportSelector.class, null).toArray(new String[0]);}}Configuration // 第三方的配置类static class AutoConfiguration1 {Beanpublic Bean1 bean1() {return new Bean1();}}Configuration // 第三方的配置类static class AutoConfiguration2 {Beanpublic Bean2 bean2() {return new Bean2();}}static class Bean1 {}static class Bean2 {}
}运行后检查返现bean1和bean2
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909648.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!