解决springRemoteRestart不起作用
springDevTools提供了热部署的工具,按照网上的教程本地可以完美的支持热部署,但是一用到remoteRestart远程热部署就失效,热部署失败,抛ClassCastException异常为了解决这个问题,咱们今天分析一下他的原理,为什么本地修改的可以热部署,远程remoteRestart就会失效(热部署时为什么会报异常)技术栈:springBoot + MVC + DUBBO + NACOS + maven打包插件spring-boot-maven-plugin
热部署原理分析当我们修改class时,springDevTools利用了不同的classLoader重新加载class,并重新启动spring,使其生效优点就是已经加载过的class并不会重新加载以便节省性能,只针对动态修改的class重新加载即可
已加载的class无法在线卸载,只能用新的classLoader去加载,这样就起到了热部署的效果旧的classLoader以及对应加载过的class会被GC回收
在springBoot启动的时候,监听启动时的事件,然后用自己的热部署classLoader去重 ...
spring事务和aop的原理
AOPspringAop大体分为两种技术方式,一种是基于动态代理的,一种是基于字节码增强的
动态代理的有基于
jdk的
基于CGLIB的
字节码增强的有
在编译时做增强的
class加载的时候做增强的
12345678910111213public enum AdviceMode { /** * JDK proxy-based advice. */ PROXY, /** * AspectJ weaving-based advice. */ ASPECTJ}
基于动态代理-PROXYAbstractAutoProxyCreator它是个抽象类,并且是bean的后置处理器,在bean创建的时候拦截,并寻找合适的切入点返回对应的proxy其中有3个实现类
InfrastructureAdvisorAutoProxyCreator如果只是开启事务则会用到此实现AOP生效规则:bean必须是Advisor类型,且role为BeanDefinition.ROLE_INFRASTRUCTURE才会生效
AspectJAwareAdviso ...
beanPostProcessor的调用流程及各种实现
在beanFactory初始化阶段会注册beanPostProcessor,它的作用就是在bean实例化前、后,初始化前、后进行拦截操作
BeanPostProcessor为最顶层的接口共有5种类型不同作用的间接接口(包含自己)
如图
InstantiationAwareBeanPostProcessor
postProcessBeforeInstantiation可以拦截bean实例化之前(不包含factoryBean#getObject),如果返回不为空,则直接调用BeanPostProcessor的后置方法并直接返回,此时bean已创建完毕(很少用)
postProcessAfterInstantiation返回值为Boolean类型,如果返回为false则不允许自动装配(很少用)
postProcessProperties自动装配,最重要的实现AutowiredAnnotationBeanPostProcessor实现自动装配
postProcessPropertyValues如果postProcessProperties返回值为null,则会调用此方法
自动装 ...
spring对bean实例化-初始化-流程
前言获取一个bean时AbstractBeanFactory#doGetBean,除非bean已经存在,否则会通过beanDefinition自动创建
创建时,如果没有beanDefinition就会报错,所以beanDefinition是一个很重要的存在
创建流程很复杂,必须要先了解bean的各种后置处理器BeanPostProcessor
spring获取bean时,底层是通过beanName获取的,如果是根据类型,那么他会先根据类型先获取name,然后根据name在获取bean
beanName可以自定义,如果非自定义默认则是classSimpleName,且第一个字母小写FactoryBean类型的beanName也是同上,如果要获取FactoryBean类型的实例话,则beanName要以"&"为前缀。否则获取的就是factoryBean对应的实际bean
以下为获取(创建)bean的大体流程
通过class类型或注解类型获取beanName不管怎样,spring底层是通过name获取对应的bean如果是根据注解获取bean,底层 ...
解析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执行完全部步骤之后都 ...
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 ...