# spring5-demo **Repository Path**: buleing/spring5-demo ## Basic Information - **Project Name**: spring5-demo - **Description**: spring5 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-01-07 - **Last Updated**: 2022-01-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # spring5-demo ### 关于bean的注入,追踪了源码后得到如下理解 > 重新梳理下了 依赖注入的时候 beanName 生成策略的问题 总分2大类, 1. 一类是通过扫描注入的,这个主要是根据 BeanNameGenerator 生成,可以自定义生成策略。 如果组件设置了value的值就用value的值 ;不指定的话就是默认生成策略就是,类名首字母小写(前提第二个字母不是大写的) @Component 及其元数据包含 @Component 的组件,还有JSR-250 @Resource JSR-330 Inject 2. 第二类就是通过结合@Configuration注解 - @import(X.class,ImportSelector.class) 默认使用 FullyQualifiedAnnotationBeanNameGenerator 生成全限定类名当做 beanName - ImportBeanDefinitionRegistrar 这是通过 registry.registerBeanDefinition(beanName,beanDefinition)注入的 - @Bean 的注入,这个就是如果指定了name的值就用name的值,没用就用方法名 ```java class ConfigurationClassBeanDefinitionReader { private void loadBeanDefinitionsForConfigurationClass( ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { if (trackedConditionEvaluator.shouldSkip(configClass)) { String beanName = configClass.getBeanName(); if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) { this.registry.removeBeanDefinition(beanName); } this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName()); return; } // 通过Import导入的 单个类,或者ImportSelector 使用的加载策略 if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } // @Bean 方式注入 的加载方式 for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } // 通过外部配置文件.groovy 或者.xml 通过@PropertySource 引入的 BeanDefinition 加载策略 loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); // 通过@Import 引入 自定义ImportBeanDefinitionRegistrar 的BeanDefinition 加载策略 loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); } } ``` ### spring-aop spring5.2.7 之后和以前的版本aop的顺序发生了调整,不是网上所说的4,5的区别。 多个aop 安装order顺序执行,越小优先级越高,最先执行,最后返回 > note: 配置类上一定要开启 @EnableAspectJAutoProxy 不开启是不会import AspectJAutoProxyRegistrar的, > 这里也可好好理解下前面通过@Import 注入bean的方式,这是一个典型的使用 ImportBeanDefinitionRegistrar 注入的案例 - 关于Pointcut 表达式,我业务方法的返回值是 Integer,而生命切点的时候使用了 execution(public int cc.realxyq.demo.aop.*(..)) 导致aop代理没有成功。所以建议修饰符部分还是使用 execution(* cc.realxyq.demo.aop.Calculator.*(..)) 的方式, 在5.3中aop的顺序是 Around环绕着 (@before-> 业务方法 -> @AfterReturning/@AfterThrowing -> @After) + @Around-before-> 环绕通知 业务方法执行之前 + @before-> 前置通知 + 业务方法 -> 就是业务方法的执行 环绕通知 通过 proceed = pjp.proceed() 执行会有异常 + @AfterReturning/@AfterThrowing -> 返回通知/或者异常通知,这两个不可能同时发生 + @After) -> 后置通知,无论正常返回或者异常返回都会执行 + @Around-AfterReturning/@AfterThrowing 环绕通知的返回/异常通知, 方法执行后或者异常的catch块中 + @Around-After 环绕通知的 后置通知 finally块中 ### 生命周期相关 > bean是实例化,依赖注入,初始化的执行顺序 - 步骤1,setBeanName 执行。。。 demoAware - 步骤2,setBeanClassLoader 执行。。。 AppClassLoader - 步骤3,setBeanFactory 执行。。。 DefaultListableBeanFactory - 步骤4,setEnvironment 执行。。。 StandardEnvironment - 步骤5,setEmbeddedValueResolver 执行。。。 EmbeddedValueResolver - 步骤6,setResourceLoader 执行。。。 AnnotationConfigApplicationContext - 步骤7,setApplicationEventPublisher 执行。。。 AnnotationConfigApplicationContext - 步骤8,setMessageSource 执行。。。 AnnotationConfigApplicationContext - 步骤9,setApplicationContext 执行。。。 AnnotationConfigApplicationContext - 如果是web环境中,在这儿还有ServletContextAware.setServletContext(ServletContext servletContext) - 步骤10,postConstruct 执行。。。 null - 步骤11,afterPropertiesSet 执行。。。 null - 步骤12,init 执行。。。 null > bean 的销毁 - 步骤13,preDestroy 执行。。。 null - 步骤14,destroy 执行。。。 null - 步骤15,close 执行。。。 null > 其实JSR-250的 @PostConstruct 和 @PreDestroy 注解就是使用 CommonAnnotationBeanPostProcessor 处理的,本身就是实现了, > 只是这个处理器构造的时候 setOrder(Ordered.LOWEST_PRECEDENCE - 3),优先级相当低 > 故此加入了自定义的POSTProcessor 实现了 DestructionAwareBeanPostProcessor[销毁的后处理器,以及从接口继承的2个方法] > DefaultListableBeanFactory - Creating shared instance of singleton bean 'demoAware' - 步骤1,DemoAware.setBeanName 方法执行了。。。 demoAware - 步骤2,DemoAware.setBeanClassLoader 方法执行了。。。 AppClassLoader - 步骤3,DemoAware.setBeanFactory 方法执行了。。。 DefaultListableBeanFactory - 步骤4,DemoAware.setEnvironment 方法执行了。。。 StandardEnvironment - 步骤5,DemoAware.setEmbeddedValueResolver 方法执行了。。。 EmbeddedValueResolver - 步骤6,DemoAware.setResourceLoader 方法执行了。。。 AnnotationConfigApplicationContext - 步骤7,DemoAware.setApplicationEventPublisher 方法执行了。。。 AnnotationConfigApplicationContext - 步骤8,DemoAware.setMessageSource 方法执行了。。。 AnnotationConfigApplicationContext - 步骤9,DemoAware.setApplicationContext 方法执行了。。。 AnnotationConfigApplicationContext - 步骤10,DemoAwareProcessor.postProcessBeforeInitialization 方法执行了。。。 cc.realxyq.demo.aware.DemoAware@46cdf8bd - 步骤11,DemoAware.postConstruct 方法执行了。。。 null - 步骤12,DemoAware.afterPropertiesSet 方法执行了。。。 null - 步骤13,DemoAware.init 方法执行了。。。 null - 步骤14,DemoAwareProcessor.postProcessAfterInitialization 方法执行了。。。 cc.realxyq.demo.aware.DemoAware@46cdf8bd > Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@619713e5, started on > - 步骤15,DemoAwareProcessor.postProcessBeforeDestruction 方法执行了。。。 cc.realxyq.demo.aware.DemoAware@46cdf8bd - 步骤16,DemoAware.preDestroy 方法执行了。。。 null - 步骤17,DemoAware.destroy 方法执行了。。。 null - 步骤18,DemoAware.close 方法执行了。。。 null