springboot目录及自动装配的实现原理

目录结构:

 static : 静态资源(js css 图片 音频  视频)

templates : 模板文件 (模板引擎freemarker ,  thymeleaf ; 默认不支持JSP)

application.properties : 配置文件

spring boot 内置了tomcat ,并且不需要打成war包再执行。

可以在application.properties中,对端口号等服务器端信息进行配置。

spring boot将各个应用/第三方框架,设置成一个个“场景” starter

选择后,spring boot会将该场景所需要的所有依赖自动注入。

例如 选择“web”,spring boot就会将web相关的依赖(tomcat json等)全部引入本项目。

@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 {

 

@SpringBootApplication : spring boot的主配置类

该注解包含 : 

@SpringBootConfiguration : 包含@Configuration,表示“配置类” : 

1、表示该类是一个配置类

2、加了@Configuration注解的类,会自动纳入spring容器中(类似spring中的@Component)

 

@EnableAutoConfiguration : 使用spring boot可以自动配置。

使用约定优于配置的原则 ,也就是说,如果不配置的情况下,会使用默认值来处理,因为绝大部分的配置都有默认值,所以可以完全不需要配置。

可以找到@SpringBootApplication所在类的包,作用: 就会将该包及所有的子包,全部纳入spring容器。

springboot会根据META-INF/spring.factories找到相应的第三方依赖,并将这些依赖引入本项目。

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

该文件在:

/home/zyf/maven_repository/org/springframework/boot/spring-boot-autoconfigure/2.2.0.M2/spring-boot-autoconfigure-2.2.0.M2-sources.jar

的META-INF目录下的spring.factories文件中

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\

...

 

总结:

编写项目时,一般会对自己写的类,以及第三方依赖 进行配置,但是spring boot 可以自动进行配置:

a、自己写的类,spring boot 通过@SpringBootConfiguration自动配置。

b、第三方依赖 通过 spring-boot-autoconfigure-2.2.0.M2-sources.jar 包中的META-INF/spring.factories进行声明,然后通过 @EnableAutoConfiguration 开启使用。

 spring-boot-autoconfigure-2.2.0.M2-sources.jar 包中包含了J2EE整合体系中需要的依赖。

c、自动装配的实现

    查看 org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration源码:

当中:

@Configuration 标识该类为一个配置类、将此类纳主SRPING IOC容器

@EnableConfigurationProperties(HttpProperties.class) : 通过HttpProperties将默认编码设置 为utf-8;

HttpProperties.java : private final Encoding encoding = new Encoding();

Encoding.java : public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

即自动装配为utf-8。

@EnableConfigurationProperties提供了prefix + 属性名 的方式 供我们修改编码。

如果需要修改默认值,在application.properties中加入:

spring.http.encoding.charset=ISO-8859-1

 

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled",
matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

@ConditionalOnXXX说明 :

@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)

含义:当属性spring.http.encoding满足要求时,此条件成立:要求spring.http.encoding.enabled =XXX , 如果没有配置,则此条件成立。也就是说,如果开发者没有配置相关的属性时,就使用默认的设置。否则使用开发者的配置。

@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) :运行在web应用中,条件成立
@ConditionalOnClass(CharacterEncodingFilter.class)  : 当这个类CharacterEncodingFilter.class存在时条件成立 

即只有当这三个要求都成立时,此类才会生效。

 

总结:

1、第一个XXXAutoConfiguration 都有许多条件限制@ConditionalOnXXX,当这些条件都满足时,此配置自动装配生效。

我们可以手动的修改自动装配:在XXXProperties文件中 加入 prefix.属性名=value

2、全局配置文件里的KEY,来源于某个Properties中的prefix+属性名

 

附@ConditionalOn条件注解列表:

@ConditionalOnBean:当容器里有指定Bean的条件下

@ConditionalOnClass:当类路径下有指定类的条件下

@ConditionalOnExpression:基于SpEL表达式作为判断条件

@ConditionalOnJava:基于JV版本作为判断条件

@ConditionalOnJndi:在JNDI存在的条件下差在指定的位置

@ConditionalOnMissingBean:当容器里没有指定Bean的情况下

@ConditionalOnMissingClass:当类路径下没有指定类的条件下

@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下

@ConditionalOnProperty:指定的属性是否有指定的值

@ConditionalOnResource:类路径是否有指定的值

@ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean

@ConditionalOnWebApplication:当前项目是Web项目的条件下。

 

查看spring boot中开启了哪些自动装配,禁止了哪些自动装配:application.properties中 加入 debug=true,执行run as 后,在输出中可以看到:

Positive matches:
-----------------



CodecsAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.http.codec.CodecConfigurer' (OnClassCondition)



CodecsAutoConfiguration.JacksonCodecConfiguration matched:
- @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper' (OnClassCondition)

。。。



Negative matches:
-----------------

ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.aspectj.lang.annotation.Aspect' (OnClassCondition)
。。。

 

其中:Positive matches:表示spring boot自动开启的装配

         Negative matches:表示spring boot未自动开启的装配

发布了112 篇原创文章 · 获赞 11 · 访问量 5万+
展开阅读全文

maven项目的坑,好难受,一天都没能解决

12-03

启动项目报如下错误,不知道该怎么解决,求大佬告知 17:29:32.702 [main] INFO c.c.p.DahApplication - [logStartupProfileInfo,684] - The following profiles are active: druid 17:29:33.157 [main] ERROR o.s.b.SpringApplication - [reportFailure,863] - Application run failed org.springframework.core.annotation.AnnotationConfigurationException: Attribute 'proxyBeanMethods' in annotation [org.springframework.boot.autoconfigure.SpringBootApplication] is declared as an @AliasFor nonexistent attribute 'proxyBeanMethods' in annotation [org.springframework.context.annotation.Configuration].; nested exception is java.lang.NoSuchMethodException: org.springframework.context.annotation.Configuration.proxyBeanMethods() at org.springframework.core.annotation.AnnotationUtils$AliasDescriptor.<init>(AnnotationUtils.java:2166) at org.springframework.core.annotation.AnnotationUtils$AliasDescriptor.from(AnnotationUtils.java:2134) at org.springframework.core.annotation.AnnotationUtils$AliasDescriptor.getOtherDescriptors(AnnotationUtils.java:2298) at org.springframework.core.annotation.AnnotationUtils$AliasDescriptor.getAttributeAliasNames(AnnotationUtils.java:2285) at org.springframework.core.annotation.AnnotationUtils.getAttributeAliasNames(AnnotationUtils.java:1795) at org.springframework.core.annotation.AnnotationUtils.getAttributeAliasMap(AnnotationUtils.java:1704) at org.springframework.core.annotation.AnnotationUtils.postProcessAnnotationAttributes(AnnotationUtils.java:1322) at org.springframework.core.annotation.AnnotatedElementUtils.getMergedAnnotationAttributes(AnnotatedElementUtils.java:365) at org.springframework.core.type.StandardAnnotationMetadata.getAnnotationAttributes(StandardAnnotationMetadata.java:121) at org.springframework.context.annotation.AnnotationConfigUtils.attributesFor(AnnotationConfigUtils.java:291) at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:93) at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:72) at org.springframework.context.annotation.AnnotatedBeanDefinitionReader.doRegisterBean(AnnotatedBeanDefinitionReader.java:224) at org.springframework.context.annotation.AnnotatedBeanDefinitionReader.registerBean(AnnotatedBeanDefinitionReader.java:145) at org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register(AnnotatedBeanDefinitionReader.java:135) at org.springframework.boot.BeanDefinitionLoader.load(BeanDefinitionLoader.java:158) at org.springframework.boot.BeanDefinitionLoader.load(BeanDefinitionLoader.java:135) at org.springframework.boot.BeanDefinitionLoader.load(BeanDefinitionLoader.java:127) at org.springframework.boot.SpringApplication.load(SpringApplication.java:722) at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:407) at org.springframework.boot.SpringApplication.run(SpringApplication.java:331) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265) at cn.com.pingtech.DahApplication.main(DahApplication.java:26) Caused by: java.lang.NoSuchMethodException: org.springframework.context.annotation.Configuration.proxyBeanMethods() at java.lang.Class.getDeclaredMethod(Class.java:2130) at org.springframework.core.annotation.AnnotationUtils$AliasDescriptor.<init>(AnnotationUtils.java:2159) ... 23 common frames omitted Disconnected from the target VM, address: '127.0.0.1:65522', transport: 'socket' 问答

使用ProxyFactoryBean的代理为什么不能执行代理的方法

07-12

//定义接口 public interface Model { public void show(); } //定义被代理的类 public class Person implements Model{ public void show() { System.out.println("处理日常的活动"); } } //代理类,使用环绕通知 public class LogginArround implements MethodInterceptor{ protected static final Log log = LogFactory.getLog(MethodBeforeAdvice.class); public Object invoke(MethodInvocation arg0) throws Throwable { System.out.println("开始审核数据"); Object rval = arg0.proceed(); System.out.println("数据审核结束"); return rval; } } <!-- bean的配置 --> <bean id="person" class="com.oak.pojo.Person"/> <bean id="logginArround" class="com.oak.proxy.LogginArround"/> <bean id="personBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>com.oak.pojo.Model</value> </property> <property name="target"> <ref local="person"/> </property> <property name="interceptorNames"> <list> <value>logginArroundAdvisor</value> </list> </property> </bean> <bean id="logginArroundAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref local="logginArround"/> </property> <property name="pattern"> <value>.*</value> </property> </bean> //测试程序 public class Main { public static void main(String[] args){ @SuppressWarnings("resource") ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = (Person) app.getBean("person"); person.show(); } } 结果只执行“处理日常的活动”,并不会执行代理的方法,这是什么原因,是jar包的问题么???求解 由于目前金币有限,所以不进行不进行选上了,大家见谅。 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览