spring-注解驱动模式
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-注解驱动模式的更多相关文章
- 【Spring注解驱动开发】使用@Lazy注解实现懒加载
		
写在前面 Spring在启动时,默认会将单实例bean进行实例化,并加载到Spring容器中.也就是说,单实例bean默认在Spring容器启动的时候创建对象,并将对象加载到Spring容器中.如果我 ...
 - 【Spring注解驱动开发】面试官:如何将Service注入到Servlet中?朋友又栽了!!
		
写在前面 最近,一位读者出去面试前准备了很久,信心满满的去面试.没想到面试官的一个问题把他难住了.面试官的问题是这样的:如何使用Spring将Service注入到Servlet中呢?这位读者平时也是很 ...
 - 【spring 注解驱动开发】Spring AOP原理
		
尚学堂spring 注解驱动开发学习笔记之 - AOP原理 AOP原理: 1.AOP原理-AOP功能实现 2.AOP原理-@EnableAspectJAutoProxy 3.AOP原理-Annotat ...
 - 你真的知道Spring注解驱动的前世今生吗?这篇文章让你豁然开朗!
		
本篇文章,从Spring1.x到Spring 5.x的迭代中,站在现在的角度去思考Spring注解驱动的发展过程,这将有助于我们更好的理解Spring中的注解设计. Spring Framework ...
 - Spring 注解驱动(一)基本使用规则
		
Spring 注解驱动(一)基本使用规则 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.基本使用 @Configur ...
 - Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用
		
Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用 Spring 系列目录(https://www.cnblogs.com/binarylei/p/1019 ...
 - 1、课程简介-Spring 注解驱动开发
		
1.课程简介-Spring 注解驱动开发
 - 0、Spring 注解驱动开发
		
0.Spring注解驱动开发 0.1 简介 <Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作 ...
 - 跟Evan学Sprign编程思想 | Spring注解编程模式【译】
		
Spring注解编程模式 概况 多年来,Spring Framework不断发展对注解.元注解和组合注解的支持. 本文档旨在帮助开发人员(Spring的最终用户以及Spring Framework和S ...
 - 【Spring注解驱动开发】聊聊Spring注解驱动开发那些事儿!
		
写在前面 今天,面了一个工作5年的小伙伴,面试结果不理想啊!也不是我说,工作5年了,问多线程的知识:就只知道继承Thread类和实现Runnable接口!问Java集合,竟然说HashMap是线程安全 ...
 
随机推荐
- CentOS7安装及配置 Zabbix全步骤,超详细教程
			
服务器太多,还在不同的平台和账户,监控不便 整个 Zabbix 监控,开始吧 一.关闭防火墙并开机不启动 sudo setenforce 0 sudo sed -i "s/SELINUX=e ...
 - OpenGL/ES关于像素渲染
			
知道着色器的人都会知道一个东西,那就是着色器分为顶点着色器与片元着色器.在移动端真正渲染到手机屏幕上的无非是一些颜色值,但是一个片元是大于一个像素的,一个片元可能包含多个像素,当然一个片元所包含的像素 ...
 - Spring系列22:Spring AOP 概念与快速入门篇
			
本文内容 Spring AOP含义和目标 AOP相关概念 声明式AOP快速入门 编程式创建代理对象 Spring AOP含义和目标 OOP: Object-oriented Programming 面 ...
 - npm install 报错:command failed git -c core.longpaths
			
最近需要angularjs,从github上下载下来程序,在安装目录下执行命令 npm install(安装依赖包)时报错了.
 - SpringMVC教程--eclipse中使用maven创建springMVC项目
			
一.在eclipse中创建maven-archetype-webapp项目: 1.新建项目选择maven项目 2.默认,下一步 3.选择maven-archetype-webapp,其他保持默认即可 ...
 - SpringBoot进阶教程(七十三)整合elasticsearch
			
Elasticsearch 是一个分布式.高扩展.高实时的搜索与数据分析引擎.它能很方便的使大量数据具有搜索.分析和探索的能力.充分利用Elasticsearch的水平伸缩性,能使数据在生产环境变得更 ...
 - cobbler check执行报错
			
httpd does not appear to be running and proxying cobbler, or SELinux is in the way. 当执行cobbler check ...
 - laravel 7 登录
			
1:路由,展示登录表单 Route::group(['prefix'=>'day','namespace'=>'day18'],function (){ // 登录 Route::get( ...
 - JMeter初级入门,安装下载使用
			
jmeter下载地址 http://jmeter.apache.org/download_jmeter.cgi jmeter本身不需要安装,只需要配置好JDK环境(Java环境),然后在在jmeter ...
 - 浅析XML
			
概述XML文档结构 每个XML文档都分为两部分:序言(Prolog)和文档元素(或文档节点) 例子:写一段XML然后简单分析一下 <?xml version="1.0" en ...