解析spring是如何向beanFactory注册bean的
背景ConfigurationClassPostProcessor该类是一个BeanFactoryPostProcessor后置处理程序,其主要功能就是扫描beanFactory已注册的bean上的注解进而处理注解对应的职责在spring的refresh阶段调用beanFactoryPostProcessors时该类才开始工作
在springContext初始化的时候通过AnnotationConfigUtils#registerAnnotationConfigProcessors向beanFactory注册该类
工作流程1. 挨个挨个扫描beanFactory中的未扫描的bean该类开始工作时,main方法所在的类已注册到beanFactory中先开始扫描main方法所在的类,并执行以下步骤2、3、4、5、6、7、8...等全部步骤,执行过程中会有新的bean注册到beanFactory中然后再从beanFactory获取所有beanNamesgetBeanDefinitionNames,过滤未扫描的bean继续扫描,直到扫完为止
每扫一个bean执行完全部步骤之后都 ...
JVM所有的参数配置详解
启动时输出jvm所有的配置
-XX:+PrintFlagsFinal
启动时输出非默认的jvm参数(人为配置的)
-XX:+PrintCommandLineFlags
循环放置安全点
-XX:+UseCountedLoopSafepoints
设置默认的hashcode
-XX:hashCode=0此类方案返回一个Park-Miller伪随机数生成器生成的随机数
-XX:hashCode=1此类方案将对象的内存地址,做移位运算后与一个随机数进行异或得到结果
-XX:hashCode=2永远返回固定值1
-XX:hashCode=3此类方案返回一个自增序列的当前值
-XX:hashCode=4此类方案返回当前对象的内存地址
内存1. -Xms1024m 最小堆内存大小(memory start)
2. -Mmx2048m 最大堆内存大小(memory max)
3. -XX:+UseCompressedOops 开启普通对象的指针压缩,此参数也会默认开启UseCompressedClassPointers 一个对象的指针默认为8字节(64bit) ...
打印日志引起的oom的解决方案
场景电商促销的逻辑,由于算价过程涉及的逻辑较多,所以有关算价的过程及结果数据都会打印下来,一旦有问题较容易排查满减赠折是促销模块比较复杂的逻辑,这次出现问题的原因是因为建了一个满减赠折的活动,满1元送一个赠品以及100个积分,几十万元送几十w个赠品,导致在打印日志的时候出现了问题
问题分析好在运维人员配置了自动dumpMemory
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/applicationNameHeapdump.hprof 在JVM内存溢出的时候自动dump内存快照,HeapDumpPath指定dump的路径,不指定的话默认输出路径为项目的根路径 经本地main方法测验,只要dump过一次,之后多次出现的oom不会dump第二次(删除dump的文件也不行)
用jProfiler分析之后发现果然是日志打印过多,就是因为送赠品送了几十w个,会产生几十w个对象,显然这是不正确的,实际应该用数值表示有多少个即可。所以几十w个对象再用日志输出的时候显然就成为了一个系统瓶颈毕竟在写完磁盘之前,这些对象一直贮存在 ...
spring对Bean的排序
大体流程不同的bean实现的接口不同、它的作用也不不同、那么他的加载顺序也不同具体可参考beanFactory对不同类型的bean加载的顺序
如果bean的类型相同、实现的接口也相同则根据
实现org.springframework.core.PriorityOrdered接口
实现org.springframework.core.Ordered接口
注解@Order
注解@Priority
以上优先级从高到低接口优先级比注解的高如果都是接口PriorityOrdered优先级更高如果都是注解@Order优先级更高数值越小的优先级就越高
代码流程具体可参考org.springframework.core.OrderComparator
默认的排序(不支持注解)
具体可参考org.springframework.core.annotation.AnnotationAwareOrderComparator
支持注解的排序
具体可参考org.springframework.core.annotation.OrderUtils
获取注解
spring 中对bean的排序 ...
springBeanFactory流程解析
spring启动流程中的refresh阶段beanFactory在refresh阶段完成配置、扫描bean、注册bean等重要操作步骤
refresh代码流程 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { ... public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { ... // 获取beanFactory,默认为new Defa ...
springMvc执行流程
spring的MVC是遵循着servlet规范的。
servlet规范当Http服务器接收请求后,Http服务器不直接调用业务类,而是把请求交给Servlet容器去处理,Servlet容器会将请求转发到具体的ServletServlet是个接口,如果想要让业务类具备处理请求的能力则需要实现此并接口,并配置到web.xml当中即可。调用servlet时如果还没创建,就加载并实例化这个Servlet,然后调用这个Servlet的service方法
123456789101112131415public interface Servlet { // Servlet容器在加载Servlet类的时候会调用init方法 void init(ServletConfig config) throws ServletException; // ServletConfig就是封装Servlet的初始化参数。可以在web.xml给Servlet配置参数 ServletConfig getServletConfig(); // 处理请求 void se ...
springMvc统一异常处理
先配置处理异常的类,然后在分析源码
mvc统一处理异常的实现常见的异常如下,基本都是参数校验的异常。参数校验需要配合jsr303的注解校验哦。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167@Slf4j@RestControllerAdvice@Conditi ...
spring-spi
java有java的spidubbo有dubbo的spispring也有自己的spi
spring spi 入口类为org.springframework.core.io.support.SpringFactoriesLoader
springBoot main启动时就用到了
1234567891011121314151617181920212223public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { ... // Context initialize 监听器 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 所有的ApplicationListener setListeners((Collection) getSpringFactoriesInstances(Ap ...
MybatisPlus语法糖的校验
mybatisPlus大大的提高了我们开发的速度。因为不需要关心sql。建立好的对象通过mybatisPlus语法糖来拼接sql。但是坏处是语法糖不好统一维护。到处都是语法糖。
所以我们规定建立一层Dao,dao层负责统一管理sql。因为要去除xml里面的sql。写sql容易出问题(字符串容易写错,不同数据库还需要关心不同的特性)建议Dao统一继承此BaseDao
一个表对应一个实体、一个mapper,一个DaoDao继承BaseDao,需要实体继承BaseDomain,mapper继承CustomBaseMapper如果实体不继承baseDomain,mapper不继承CustomBaseMapper,则dao也无法继承BaseDao
如何有效(强制)的避免以下相同拼接的sql出现在多处?例如以下的sql拼接语法糖
123456789101112131415161718192021222324252627public DemoService { @Autowired DemoDao demoDao; public void ...
基于Spring的代码分层校验
常见的代码分层图
分层很明确,先说缺点
service层可以依赖多个dao层一个表肯定对应一个dao。如果一个service直接操作多张表(dao)也没问题,但是有可能所有表的操作都封闭在一个service中。
如果后期维护某一张表的时候你就得需要屡下所有调用此表的service,花费时间不说,还有可能漏掉。
如果对其中一个表进行别的业务复用的话,则需要把代码抽离出来,并且有可能开发人员不抽离,而是直接copy粘贴,导致代码原来越乱。
所以建议一个表对应一个dao和一个service,其中service只能操作自己的表(dao)。要是操作其他的表只能依赖其对应的service
上图没有明确表明哪些是可以互相依赖(service依赖其他service,dao可以依赖其他dao...),哪些不可以互相依赖。所以我们认为都是可以相互依赖的。互相依赖比较混乱。
dao专门负责管理sql,如果对一个实体的curd还涉及到另外其他的实体curd。那么这就显然属于业务范畴了,应该放在service。所以在dao这一层。我们不能让他操作多张表(不能有互相依赖)
没有强制的依赖校验。如果 ...