bean create before
resolveBeforeInstantiation(beanName, mbdToUse); => InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(beanClass, beanName);
bean instance before
determineConstructorsFromBeanPostProcessors(beanClass, beanName); => SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors(beanClass, beanName); @Autowired 构造器
bean instance after
bean instance after merge bean query
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); => MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
bean instance after earlybean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); => SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference(exposedObject, beanName);
bean field setting
属性填充 populateBean(beanName, mbd, instanceWrapper);
bean initialize
bean initialize before
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); =>
bean initialize before
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); =>
bean initialize register distroy
registerDisposableBeanIfNecessary(beanName, bean, mbd); => DestructionAwareBeanPostProcessor
bean create after
destroySingleton(beanName) => DestructionAwareBeanPostProcessor#postProcessBeforeDestruction(this.bean, this.beanName);
NamingService -> NacosNamingService => registerInstance
思考: 为什么整合Nacos注册中心后,服务启动就会自动注册,Nacos是如何实现自动服务注册的?
Tomcat启动之后, 在ServletWebServerApplicationContext中,发布事件 ServletWebServerInitializedEvent
spring-cloud-commons 包 AbstractAutoServiceRegistration 监听 WebServerInitializedEvent
public abstract class AbstractAutoServiceRegistrationimplements AutoServiceRegistration, ApplicationContextAware,ApplicationListener {public void onApplicationEvent(WebServerInitializedEvent event) {bind(event); // .... register();}
}
start => AbstractApplicationContext.refresh -> finishRefresh() -> getLifecycleProcessor().onRefresh(); -> start()
public class NacosWatchimplements ApplicationEventPublisherAware, SmartLifecycle, DisposableBean {@Overridepublic void start() {...NamingService namingService = nacosServiceManager.getNamingService(properties.getNacosProperties());try {namingService.subscribe(properties.getService(), properties.getGroup(),Arrays.asList(properties.getClusterName()), eventListener);}catch (Exception e) {log.error("namingService subscribe failed, properties:{}", properties, e);}this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(this::nacosServicesWatch, this.properties.getWatchDelay());}}}
EurekaServerInitializerConfiguration
所有的单例bean实例化之后调用
思考:为什么@Bean修饰的RestTemplate加上@LoadBalanced就能实现负载均衡功能?
@Bean
@LoadBalanced
public RestTemplate restTemplate() {return new RestTemplate();
}
LoadBalancerAutoConfiguration
对SmartInitializingSingleton的扩展,为所有用@LoadBalanced修饰的restTemplate(利用了@Qualifier 限定符)绑定实现了负载均衡逻辑的拦截器LoadBalancerInterceptor
@LoadBalanced
@Autowired(required = false)
private List restTemplates = Collections.emptyList();@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider> restTemplateCustomizers) {return () -> restTemplateCustomizers.ifAvailable(customizers -> {for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {for (RestTemplateCustomizer customizer : customizers) {customizer.customize(restTemplate);}}});
}
/*** Annotation to mark a RestTemplate or WebClient bean to be configured to use a* LoadBalancerClient.* @author Spencer Gibb*/
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier //Qualifier
public @interface LoadBalanced {
}
LoadBalancerInterceptor
@Configuration(proxyBeanMethods = false)@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")static class LoadBalancerInterceptorConfig {@Beanpublic LoadBalancerInterceptor loadBalancerInterceptor(LoadBalancerClient loadBalancerClient,LoadBalancerRequestFactory requestFactory) {return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);}@Bean@ConditionalOnMissingBeanpublic RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {return restTemplate -> {List list = new ArrayList<>(restTemplate.getInterceptors());list.add(loadBalancerInterceptor);restTemplate.setInterceptors(list);};}}
思考:为什么Feign接口可以通过@Autowired直接注入使用?Feign接口是如何交给Spring管理的?
@FeignClient(value = "order-service", path = "/order")
public interface OrderFeignService {@GetMapping(value = "/info/{productId}")public String findOrderInfoByProductId(@PathVariable("productId") Integer productId);
}
@SpringBootApplication
@EnableFeignClients(basePackages = "com.mx.use.feign")
@EnableHystrix
@EnableHystrixDashboard //开启 Hystrix 监控功能
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {...
}
FactoryBean => FeignClientsRegistrar -> scan(FeignClient) -> registerFeignClient -> FeignClientFactoryBean

@Override
public Object getObject() {return getTarget(); //
}
AbstractSentinelInterceptor#preHandle
public abstract class AbstractSentinelInterceptor implements HandlerInterceptor {...@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {try {String resourceName = getResourceName(request);if (StringUtil.isEmpty(resourceName)) {return true;}if (increaseReferece(request, this.baseWebMvcConfig.getRequestRefName(), 1) != 1) {return true;}// Parse the request origin using registered origin parser.String origin = parseOrigin(request);String contextName = getContextName(request);ContextUtil.enter(contextName, origin);//Sentinel入口Entry entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.IN);request.setAttribute(baseWebMvcConfig.getRequestAttributeName(), entry);return true;} catch (BlockException e) {try {handleBlockException(request, response, e);} finally {ContextUtil.exit();}return false;}}...
}
SentinelDataSourceHandler
#Sentinel持久化读数据源设计,利用了SmartInitializingSingleton扩展点
SentinelDataSourceHandler#afterSingletonsInstantiated
# 注册一个FactoryBean类型的数据源
》SentinelDataSourceHandler#registerBean
》》NacosDataSourceFactoryBean#getObject
# 利用FactoryBean获取到读数据源
》》new NacosDataSource(properties, groupId, dataId, converter)
NacosDataSourceFactoryBean
public class NacosDataSourceFactoryBean implements FactoryBean {...@Overridepublic NacosDataSource getObject() throws Exception {...return new NacosDataSource(properties, groupId, dataId, converter);}...
}
SentinelDataSourceHandler
public class SentinelDataSourceHandler implements SmartInitializingSingleton {...@Overridepublic void afterSingletonsInstantiated() {...//sentinel.nacos.config.serverAddr=${sentinel.nacos.config.serverAddr}//NacosDataSourceAbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties.getValidDataSourceProperties();abstractDataSourceProperties.setEnv(env);abstractDataSourceProperties.preCheck(dataSourceName);registerBean(abstractDataSourceProperties, dataSourceName+ "-sentinel-" + validFields.get(0) + "-datasource"); //NacosDataSource...}...
}
GlobalTransactionScanner

GlobalTransactionalInterceptor
public class GlobalTransactionalInterceptor implements ConfigurationChangeListener, MethodInterceptor, SeataInterceptor {...@Overridepublic Object invoke(final MethodInvocation methodInvocation) throws Throwable {Class> targetClass =methodInvocation.getThis() != null ? AopUtils.getTargetClass(methodInvocation.getThis()) : null;Method specificMethod = ClassUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass);if (specificMethod != null && !specificMethod.getDeclaringClass().equals(Object.class)) {final Method method = BridgeMethodResolver.findBridgedMethod(specificMethod);final GlobalTransactional globalTransactionalAnnotation =getAnnotation(method, targetClass, GlobalTransactional.class);final GlobalLock globalLockAnnotation = getAnnotation(method, targetClass, GlobalLock.class);boolean localDisable = disable || (degradeCheck && degradeNum >= degradeCheckAllowTimes);if (!localDisable) {if (globalTransactionalAnnotation != null || this.aspectTransactional != null) {AspectTransactional transactional;if (globalTransactionalAnnotation != null) {transactional = new AspectTransactional(globalTransactionalAnnotation.timeoutMills(),globalTransactionalAnnotation.name(), globalTransactionalAnnotation.rollbackFor(),globalTransactionalAnnotation.noRollbackForClassName(),globalTransactionalAnnotation.noRollbackFor(),globalTransactionalAnnotation.noRollbackForClassName(),globalTransactionalAnnotation.propagation(),globalTransactionalAnnotation.lockRetryInterval(),globalTransactionalAnnotation.lockRetryTimes());} else {transactional = this.aspectTransactional;}// 执行事务 transactionalTemplate.execute()return handleGlobalTransaction(methodInvocation, transactional);} else if (globalLockAnnotation != null) {return handleGlobalLock(methodInvocation, globalLockAnnotation);}}}return methodInvocation.proceed();}...
}
public class TransactionalTemplate {public Object execute(TransactionalExecutor business) throws Throwable {// 1. Get transactionInfoTransactionInfo txInfo = business.getTransactionInfo();if (txInfo == null) {throw new ShouldNeverHappenException("transactionInfo does not exist");}// 1.1 Get current transaction, if not null, the tx role is 'GlobalTransactionRole.Participant'.GlobalTransaction tx = GlobalTransactionContext.getCurrent();// 1.2 Handle the transaction propagation.Propagation propagation = txInfo.getPropagation();SuspendedResourcesHolder suspendedResourcesHolder = null;try {switch (propagation) {case NOT_SUPPORTED:// If transaction is existing, suspend it.if (existingTransaction(tx)) {suspendedResourcesHolder = tx.suspend();}// Execute without transaction and return.return business.execute();case REQUIRES_NEW:// If transaction is existing, suspend it, and then begin new transaction.if (existingTransaction(tx)) {suspendedResourcesHolder = tx.suspend();tx = GlobalTransactionContext.createNew();}// Continue and execute with new transactionbreak;case SUPPORTS:// If transaction is not existing, execute without transaction.if (notExistingTransaction(tx)) {return business.execute();}// Continue and execute with new transactionbreak;case REQUIRED:// If current transaction is existing, execute with current transaction,// else continue and execute with new transaction.break;case NEVER:// If transaction is existing, throw exception.if (existingTransaction(tx)) {throw new TransactionException(String.format("Existing transaction found for transaction marked with propagation 'never', xid = %s", tx.getXid()));} else {// Execute without transaction and return.return business.execute();}case MANDATORY:// If transaction is not existing, throw exception.if (notExistingTransaction(tx)) {throw new TransactionException("No existing transaction found for transaction marked with propagation 'mandatory'");}// Continue and execute with current transaction.break;default:throw new TransactionException("Not Supported Propagation:" + propagation);}// 1.3 If null, create new transaction with role 'GlobalTransactionRole.Launcher'.if (tx == null) {tx = GlobalTransactionContext.createNew();}// set current tx config to holderGlobalLockConfig previousConfig = replaceGlobalLockConfig(txInfo);try {// 2. If the tx role is 'GlobalTransactionRole.Launcher', send the request of beginTransaction to TC,// else do nothing. Of course, the hooks will still be triggered.beginTransaction(txInfo, tx);Object rs;try {// Do Your Businessrs = business.execute();} catch (Throwable ex) {// 3. The needed business exception to rollback.completeTransactionAfterThrowing(txInfo, tx, ex);throw ex;}// 4. everything is fine, commit.commitTransaction(tx);return rs;} finally {//5. clearresumeGlobalLockConfig(previousConfig);triggerAfterCompletion();cleanUp();}} finally {// If the transaction is suspended, resume it.if (suspendedResourcesHolder != null) {tx.resume(suspendedResourcesHolder);}}}
}