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是线程安全 ...
随机推荐
- Nginx 配置apple-app-site-association
ios突然给我发了如上链接和一个json,说他那边需要放一个 apple-app-site-association 文件用来支持他那边的功能,文件不需要后缀. 先说一下要求:线上官网的地址后面跟上他所 ...
- windows server2012 r2 .net framework 3.5失败
拿到手的虚拟机系统是Windows server 2012R2,本想着安装SQlserver2012轻轻松松,结果途中警告未安装.NET Framework 3.5.于是找了个.NET Framewo ...
- Meterpreter核心命令
实验目的 掌握Meterpreter常见的基本命令的使用 实验原理 1.Meterpreter介绍 meterpreter是metasploit框架中的一个扩展模块,作为溢出成功以后的攻击载荷使用,攻 ...
- python数据结构:数组和列表
线性结构有两种:数组和列表 array和list 其中list各项操作的时间复杂度如下 因为insert是在头部插入 所以列表所有元素后移,时间复杂度为O(n) remove移除列表中某个值的第一个匹 ...
- 分享几个你可能不知道的交互式Git 命令
摘要:本文中讲述的几个交互式 Git 命令可以帮助你将文件的特定部分组合成提交. 本文分享自华为云社区<Git你有可能不知道交互式暂存>,作者:龙哥手记. 本节中的几个交互式 Git 命令 ...
- NFA转化为DFA
NFA(不确定的有穷自动机)转化为DFA(确定的有穷自动机) NFA转换DFA,通常是将带空串的NFA(即:ε-NFA)先转化为不带空串的NFA(即:NFA),然后再转化为DFA. 提示:ε是空串的意 ...
- Python实现JSON序列化和反序列化
在我的应用中,序列化就是把类转成符合JSON格式的字符串,反序列化就是把JSON格式的字符串转换成类.C#的话直接用Newtonsoft.JSON就可以了,非常好用.本来以为python也会有类似的库 ...
- 三大数据库 sequence 之华山论剑 (下篇)
MySQL 5.7 MYISAM ENGINE 以下是 MySQL 5.7 MYISAM ENGINE 中的运行结果 mysql> CREATE TABLE tb_test5 ( -> t ...
- Apache Ranger 编译安装部署
1. 概述 Apache Ranger是大数据领域的一个集中式安全管理框架,目的是通过制定策略(policies)实现对Hadoop组件的集中式安全管理.用户可以通过Ranger实现对集群中数据的安全 ...
- 命令行窗口cmd:访问C盘根目录和其他盘
1:访问C盘: cd.. 往前推一个目录 以此类推,多用几次cd..即可退回到根目录 2:访问桌面文件夹 由于cmd命令行中>号的存在我们不能直接访问其他文件,所以用cd将>删去 所以 用 ...