spring web装配原理:

 /**
* WebApplicationInitializer Spring MVC 提供接口。
*
* Spring中的web自动配置,也是可以,
*/ /**
* AbstractContextLoaderInitializer 装配原理:
* ContextLoaderListener是标准ServletContextListener的实现,监听ServletContext生命周期
* 启动-Servlet调用ServletContextListener实现类的默认方法。contextInitialized
* 关闭-contextDestroyed
*/ /**
* 运行到3.0中,web.xml配置文件中的ContextLoaderListener的方式可替换为AbstractContextLoaderInitializer的实现类
* 只需要实现createRootApplicationContext()方法
*
* 注意:官方不推荐,使用AbstractContextLoaderInitializer进行,ContextLoaderListener允许重复注册到SevletContext。
* 如果Web应用的ClassPath下同时存在多个AbstractContextLoaderInitializer的实现类,抛异常IllegalStateException
*/
public class SpringWeb2 {
/**
* AbstractDispatcherServletInitializer装配原理
*
* AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer的子类
* 补上没有注册DispatcherServlet,且没有实现父类的createRootApplicationContext()
* 提供注册Filter模板方法
*/
}
public class SpringWeb3 {
/**
* AbstractAnnotationConfigDispatcherServletInitializer装配原理
* 由于其父类AbstractDispatcherServletInitializer没有实现createRootApplicationContext()
* 且需要子类实现:protected abstract WebApplicationContext createServletApplicationContext();
*
* 而AbstractAnnotationConfigDispatcherServletInitializer直接实现了这两个方法
*
* Root WebApplicationContext 和DispatcherServlet WebApplicationContext,都
* 采用注解驱动Web应用上下文实现:AnnotationConfigWebApplicationContext
*
*/ /**
* @Nullable:字段可以为空
*/
}

import原理:

/**
* @author beter.quan
* @date 2020/10/20 2:20 下午
*/
public class Theory {
/**
* 装载@Configuration Class,之前没有@ComponentScan,所以只能使用导入注解@Import
* <context:annotation-config>对应的BeanDefinitionParser实现为:AnnotationConfigBeanDefinitionParser
* 里面的方法:public BeanDefinition parse(Element element, ParserContext parserContext)
* 没有直接解析BeanDefinition实例,调用了
* AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
*
* @Configuration 处理类ConfigurationClassPostProcessor 被封装为BeanDefinition并注册
*
* ConfigurationClassPostProcessor xml配置驱动,注解驱动,都通过registerAnnotationConfigProcessors方法进行装载
* 且为最高优先级的BeanFactoryPostProcessor实现
* 注释解析
* p>This post processor is priority-ordered as it is important that any
* * {@link Bean} methods declared in {@code @Configuration} classes have
* * their corresponding bean definitions registered before any other
* * {@link BeanFactoryPostProcessor} executes.
*
*/ /**
* AbstractApplicationContext#refresh()调用时,spring容器(BeanFactory)将ConfigurationClassPostProcessor 初始化为Bean
* 随后invokeBeanFactoryPostProcessors实际上是使用:
* PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors。这个方法里面;
* private static void invokeBeanFactoryPostProcessors(
* Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
*
* for (BeanFactoryPostProcessor postProcessor : postProcessors) {
* postProcessor.postProcessBeanFactory(beanFactory);
* }
* 调用接口的实现类的postProcessBeanFactory 方法
* 例如:ConfigurationClassPostProcessor#public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
*
* 执行postProcessBeanFactory期间,ConfigurationClassParser是将spring BeanDefinition 进行注解原信息解析
* 解析的时候有两个parse重载方法,
* @Configuration Class被ConfigurationClass 类所抽象,且处理方法为processConfigurationClass,但真正执行的是doProcessConfigurationClass
* 在doProcessConfigurationClass方法中,@Import @ImportResource @Bean都被处理
*
*
* 解析后,ConfigurationClass集合将被ConfigurationClassBeanDefinitionReader 再次注册Spring Bean
*/ /**
* ConfigurationClassBeanDefinitionReader 将@Import @ImportResource @Bean 一并注册
*/
}

@Conditional

public class OwnerTest {
/**
* @Profile 配置条件装配---静态激活和配置
*/ /**
* @Conditional 指定多个或一个Condiction,所有condiction匹配----》条件成立
*
* 这里的匹配只的是执行condiction返回true
* boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
* ConditionContext这个参数包含Spring应用上下文相关的:BeanDefinitionRegistry,ConfigurableBeanFactory
*/
/**
* 还有包括:
* @ConditionalOnClass
* @ConditionalOnBean
* @ConditionalOnProperty
*
*/
}

@conditional原理:

/**
* @author beter.quan
* @date 2020/10/20 8:34 下午
* @Conditional条件装配原理
*/
public class TheoryConditional {
/**
* @Conditional(ProfileCondition.class)
* public @interface Profile
*/
// ProfileCondition 代码内容一下
class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {//
if (context.getEnvironment().acceptsProfiles(Profiles.of((String[]) value))) {
return true;
}
}
return false;
}
return true;
}
/**
* @Conditional的统一处理实现ConditionEvaluator
*ConditionEvaluator里面的方法
* public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase)
* 将AnnotatedTypeMetadata标注的所有COndition实例一一匹配,不匹配放回true 跳过。
*/
}
}

自定义conditional注解

先定义Condition,实现该接口

/**
* @author beter.quan
* @date 2020/10/20 8:10 下午
*/
public class OnSystemPropertyCondition implements Condition { @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 获取ConditionalOnSystemProperty所有属性方法的值,这里就是属性名name对应的值
MultiValueMap<String, Object> attibutes = metadata.getAllAnnotationAttributes(ConditionalOnSystemProperty.class.getName());
String propertyName = (String) attibutes.getFirst("name");
String propertyValue = (String) attibutes.getFirst("value");
String systemPropertyValue = System.getProperty(propertyName);
if (Objects.equals(systemPropertyValue, propertyValue)) {
System.out.printf("属性名称 %s 找到匹配 %s", propertyName, propertyValue);
return true;
}
return false;
}
}

编写自定义条件注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {
String name(); String value();
}

编写配置类

@Configuration
public class CondictionalMessageConfiguration {
@ConditionalOnSystemProperty(name = "language", value = "Chinese")
@Bean("message")
public String cMessage() {
return "中文";
} @ConditionalOnSystemProperty(name = "language", value = "English")
@Bean("message")
public String eMessage() {
return "English";
} }

测试

/**
* @author beter.quan
* @date 2020/10/20 8:22 下午
*/
public class ConditionalTest {
public static void main(String[] args) {
System.setProperty("language", "English");
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(CondictionalMessageConfiguration.class);
context.refresh();
String message = context.getBean("message", String.class);
System.out.println(message);
}
}

spring-注解驱动模式的更多相关文章

  1. 【Spring注解驱动开发】使用@Lazy注解实现懒加载

    写在前面 Spring在启动时,默认会将单实例bean进行实例化,并加载到Spring容器中.也就是说,单实例bean默认在Spring容器启动的时候创建对象,并将对象加载到Spring容器中.如果我 ...

  2. 【Spring注解驱动开发】面试官:如何将Service注入到Servlet中?朋友又栽了!!

    写在前面 最近,一位读者出去面试前准备了很久,信心满满的去面试.没想到面试官的一个问题把他难住了.面试官的问题是这样的:如何使用Spring将Service注入到Servlet中呢?这位读者平时也是很 ...

  3. 【spring 注解驱动开发】Spring AOP原理

    尚学堂spring 注解驱动开发学习笔记之 - AOP原理 AOP原理: 1.AOP原理-AOP功能实现 2.AOP原理-@EnableAspectJAutoProxy 3.AOP原理-Annotat ...

  4. 你真的知道Spring注解驱动的前世今生吗?这篇文章让你豁然开朗!

    本篇文章,从Spring1.x到Spring 5.x的迭代中,站在现在的角度去思考Spring注解驱动的发展过程,这将有助于我们更好的理解Spring中的注解设计. Spring Framework ...

  5. Spring 注解驱动(一)基本使用规则

    Spring 注解驱动(一)基本使用规则 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.基本使用 @Configur ...

  6. Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用

    Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用 Spring 系列目录(https://www.cnblogs.com/binarylei/p/1019 ...

  7. 1、课程简介-Spring 注解驱动开发

    1.课程简介-Spring 注解驱动开发

  8. 0、Spring 注解驱动开发

    0.Spring注解驱动开发 0.1 简介 <Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作 ...

  9. 跟Evan学Sprign编程思想 | Spring注解编程模式【译】

    Spring注解编程模式 概况 多年来,Spring Framework不断发展对注解.元注解和组合注解的支持. 本文档旨在帮助开发人员(Spring的最终用户以及Spring Framework和S ...

  10. 【Spring注解驱动开发】聊聊Spring注解驱动开发那些事儿!

    写在前面 今天,面了一个工作5年的小伙伴,面试结果不理想啊!也不是我说,工作5年了,问多线程的知识:就只知道继承Thread类和实现Runnable接口!问Java集合,竟然说HashMap是线程安全 ...

随机推荐

  1. 设计DFA接受{0,1}上的字符串ω,且ω是3倍数的二进制表示

    DFA设计 设计DFA接受{0,1}上的字符串ω,且ω是3倍数的二进制表示 先叙述下思路: 要想证明某数是3的倍数可以让其除以3看余数是否为零即可,现在我们的问题就是如何计算一串二进制数除以3所得的余 ...

  2. [旧][Android] ButterKnifeProcessor 工作流程分析

    备注 原发表于2016.05.21,资料已过时,仅作备份,谨慎参考 前言 在 [Android] ButterKnife 浅析 中,我们了解了 ButterKnife 的用法,比较简单. 本次文章我们 ...

  3. 带你玩转CompletableFuture异步编程

    前言 最近在忙生活的第一个OKR,这个等等后面具体聊聊,今天开始恢复每周一篇原创,感谢小伙伴的不离不弃.这篇文章也是最近在Code Review的时候,看到的大家代码,想整体推下大家异步编程的思想,由 ...

  4. 【C# 线程】线程池 epoll和IOCP之比较

    总结:IOCP :我的打印文件放在店里面排队,轮到我打印了,店长帮我打印一下,打印好了通知我来拿 Epoll  :我的打印文件放在店里面排队,轮到我叫我一下,我自己来打印. 直入正题:Epoll 是L ...

  5. maven配置本地仓库和远程仓库

    配置本地仓库 修改maven安装目录下conf/settings.xml,也可以在idea配置中覆盖 <localRepository>E:\maven\MavenRepository&l ...

  6. Android studio常用快捷键导包的设置

    下面是一些快捷键的使用还有快速导包的设置 1. Ctrl+G 同时按下Ctrl+G快捷键弹出快速定位框,在框中输入行数点击OK即可快速切换到对应的行数,如图2.17所示. 2. Ctrl+E 同时按下 ...

  7. Hive表数据同步到es

    1.首先服务器节点,进入到对应的数据库.2. 然后找到要同步的表,show create table + 表名查看一下或者自己可以新建一个表,用来测试原表,如下 CREATE TABLE `wb_tm ...

  8. Leaflet:控件Control相关

    Leaflet官方文档中只给出了4种控件:Zoom.Attribution.Layers.Scale:它们都是继承自Control类,具体可以参考Control. Control Zoom.Scale ...

  9. Chrome:F12开发者模式下console不打印信息

    控制台不打印信息的解决方法 你要看看你是否在之前进行过查找关键字操作,操作之后忘记删去这个关键字,导致console中只会留下对于该关键字的查询结果.

  10. curl 命令常用

    参考: https://www.cnblogs.com/name-lizonglin/p/12167808.html -- 测试 请求返回时间  测试Pod 之间解析时间   用key为空字符串查me ...