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是线程安全 ...
随机推荐
- showdoc升级问题,showdoc错误日志
showdoc自带错误日志.目录位于网站根目录的server/Application/Runtime/Logs/Api目录下,如果没有任何内容需要添加可写权限. showdoc升级后,建议把MySQL ...
- scrapy爬取《坏蛋是怎样练成的4》
scrapy具体介绍就不用说了,自己百度一下.或者参考以下文档 https://blog.csdn.net/u011054333/article/details/70165401 直接在cmd里运行 ...
- CobaltStrike逆向学习系列(13):RDI 任务执行流程分析
这是[信安成长计划]的第 13 篇文章 0x00 目录 0x01 任务号 0x02 功能执行 0x03 结果接收 在上一篇文章中已经讲明了 RDI 类型的任务在发布时候的流程,接下来就是执行了,文中不 ...
- Spark学习记录
SpringStrongGuo Hadoop与Spark Hadoop主要解决,海量数据的存储和海量数据的分析计算. Spark主要解决海量数据的分析计算. Spark运行模式 1)Local:运行在 ...
- HTTP攻击与防范-PHP安全配置
实验目的 1.了解PHP攻击带来的危险性. 2.掌握PHP攻击的原理与方法 3.掌握防范攻击的方法 实验原理 由于网站服务器是以单一系统使用者的模式在运行,因此这个系统的使用者账号必须能够读取每个使用 ...
- ISISv6协议测试——信而泰网络测试仪实操
文章关键词 ISIS协议:路由协议:协议测试: 一.前言: isis是一种与ospf很相似的网络协议(属于动态路由协议),它被应用在巨大规模网络,如运营商以及银行等.同样的它也是基于链路状态算法,支持 ...
- vim中的incsearch不好用,没有动态效果,为什么——incsearch is not working
虽然使用Linux好多年了,使用vim也好多年了,但是使用vim进行search的时候重来也没有想过要添加动态效果,近来突然有了兴致想要添加这个功能,不过发现居然不好用,在百度上找了好长时间居然没有一 ...
- FTP服务器日志解析
转至:https://blog.csdn.net/weixin_34320724/article/details/92045244 FTP是老牌的文件传输协议,在网络中应用非常广泛.本节就Vsftp服 ...
- ImageView和使用第三方库加载网络图片
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android: ...
- 微信小程序书简易支付
这里结合了上一篇的手机号登录接下来的实现功能 https://www.cnblogs.com/xiaoyantongxue/p/15472915.html 登录后进入课程选择页面 1:数据库填入数据 ...