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. 攻防世界之Web_supersqli

    题目 本题考查sql注入传送门https://www.cnblogs.com/shacker/p/15917173.html 按照SQL注入一步一步执行 发现有2个列 然后用union select联 ...

  2. 【性能测试实战】jmeter + k8s + 微服务 + skywalking + efk,测试都在学的热门技术

    原文持续更新完善:https://www.cnblogs.com/uncleyong/p/15475614.html 前言:当前的热门主流技术是哪些?测开为啥那么火?90%以上的测试对测开认识不准确 ...

  3. [题解]Codeforces Round #519 - C. Smallest Word

    [题目] C. Smallest Word [描述] IA有一个由若干个'a'和'b'组成的字符串,IA可以翻转该字符串的任意长的前缀,IA想通过这样的操作得到一个字典序最小的字符串,求一种可能的翻转 ...

  4. BGP4协议测试——信而泰网络测试仪实操

    文章关键词 BGP:路由测试:协议测试:矢量路由协议: 一.前言: BGP是自治系统外部路由协议,用来在AS之间传递路由信息 路径矢量路由协议,从设计上避免了环路的发生 其路由信息中携带了所经过的全部 ...

  5. python基础之序列类型的方法——列表&元组

    Hello大家好,我是python学习者小杨同学,上次跟大家分享关于python的数值类型和序列类型,本次就承接上一节的内容,说一说序列类型的方法. 序列类型的方法,简单的来说就是四个字:增删改查.随 ...

  6. 安卓Java主页面的编写

    1 package com.example.first; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 5 import android ...

  7. mapreduce—shuffle图解

  8. selenium+python自动化105 - selenium 如何在已打开的浏览器上继续运行自动化脚本?

    前言 使用selenium 做web自动化的时候,经常会遇到这样一种需求,是否可以在已经打开的浏览器基础上继续运行自动化脚本? 这样前面的验证码登录可以手工点过去,后面页面使用脚本继续执行,这样可以解 ...

  9. websocket原理和基于c/c++实现的websocket协议栈(更新中)

    参考: 博客1:http://blog.sina.com.cn/s/blog_bf397e780102w25k.html https://www.cnblogs.com/barrywxx/p/7412 ...

  10. LeetCode-039-组合总和

    组合总和 题目描述:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数 ...