- Spring扩展点 
  - Bean的生命周期中的BeanPostProcessor扩展点
- Spring扩展点梳理
 
- Spring扩展点应用场景 
  - 整合Nacos 服务注册 
    - ApplicationListener扩展场景——监听容器中发布的事件
- Lifecycle Nacos 发布订阅 & Eureka 服务启动、同步、剔除
- Lifecycle扩展场景——管理具有启动、停止生命周期需求的对象
 
- 整合Nacos 发布订阅 NacosWatch
- 整合Eureka 注册 
    - 扩展: Eureka Server端上下文的初始化是在SmartLifecycle#start中实现的
 
- 整合Ribbon 
    - SmartInitializingSingleton扩展场景—— 对容器中的Bean对象进行定制处理
 
- 整合Feign 
    - FactoryBean的扩展场景——将接口生成的代理对象交给Spring管理
 
- 整合sentinel 
    - HandlerInterceptor扩展场景——对mvc请求增强
- SmartInitializingSingleton&FactoryBean结合场景——根据类型动态装配对象
 
- 整合seata 
    - AbstractAutoProxyCreator&MethodInterceptor结合场景——实现方法增强
 
 
- 整合Nacos 服务注册 
    
Spring扩展点
Bean的生命周期中的BeanPostProcessor扩展点
-  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);- AutowiredAnnotationBeanPostProcessor @Autowired @Value
- CommonAnnotationBeanPostProcessor @Resource @PostConstruct @PreDestroy
 
-  bean instance after earlybean 
 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); => SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference(exposedObject, beanName);
 
-  
-  bean field setting 
 属性填充 populateBean(beanName, mbd, instanceWrapper);- 属性填充 before => InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)
- 属性填充 after => field属性 和 setter方式
 InstantiationAwareBeanPostProcessor.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)
 InstantiationAwareBeanPostProcessor.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
 
-  bean initialize -  bean initialize before 
 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); =>- InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(result, beanName); initmethod @PostConstruct
- ApplicationContextAwareProcessor.postProcessBeforeInitialization(result, beanName); Aware: ApplicationContextAware、ApplicationEventPublisherAware、EnvironmentAware
 
-  bean initialize before 
 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); =>- AbstractAutoProxyCreator.postProcessAfterInitialization(result, beanName); AOP (wrapIfNecessary->createAopProxy().getProxy(classLoader); Cglib/Jdk)
 
-  bean initialize register distroy 
 registerDisposableBeanIfNecessary(beanName, bean, mbd); => DestructionAwareBeanPostProcessor
 
-  
-  bean create after 
 destroySingleton(beanName) => DestructionAwareBeanPostProcessor#postProcessBeforeDestruction(this.bean, this.beanName);
Spring扩展点梳理
- BeanFactoryPostProcessor 
  - BeanDefinitionRegistryPostProcessor 
    - postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) # 注册Bean 定义
 
 
- BeanDefinitionRegistryPostProcessor 
    
- BeanPostProcessor 
  - InstantiationAwareBeanPostProcessor 
    - postProcessBeforeInstantiation
- postProcessAfterInstantiation
- postProcessProperties
- postProcessPropertyValues
 
- AbstractAutoProxyCreator 
    - postProcessAfterInitialization # 实例化之后AOP支持
 
 
- InstantiationAwareBeanPostProcessor 
    
- @Import 
  - ImportBeanDefinitionRegistrar 
    - registerBeanDefinitions
 
- ImportSelector 
    - String[] selectImports(AnnotationMetadata importingClassMetadata)
- default Predicate getExclusionFilter() { return null;}
 
 
- ImportBeanDefinitionRegistrar 
    
- Aware 
  - ApplicationContextAware 
    - setApplicationContext(ApplicationContext applicationContext)
 
- BeanFactoryAware 
    - setBeanFactory(BeanFactory beanFactory)
 
 
- ApplicationContextAware 
    
- InitializingBean || @PostConstruct
- FactoryBean (动态创建Bean)(&beanName factoryBean.getObject | beanName beanFactory.getBean)(Mybatis#mapper、Openfeign) 
  - T getObject() throws Exception;
- Class<?> getObjectType();
- default boolean isSingleton() { return true; }
 
- SmartInitializingSingleton Bean 
  - void afterSingletonsInstantiated(); # 初始化之后调用 过滤器…
 
- ApplicationListener 
  - void onApplicationEvent(E event);
 
- Lifecycle 
  - SmartLifecycle 
    - default boolean isAutoStartup() { return true; }
- default void stop(Runnable callback)
 
- LifecycleProcessor
 
- SmartLifecycle 
    
- HandlerInterceptor 
  - default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
- default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception
- default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception
 
- MethodInterceptor 
  - Object invoke(MethodInvocation invocation) throws Throwable;
 
Spring扩展点应用场景
整合Nacos 服务注册
ApplicationListener扩展场景——监听容器中发布的事件
NamingService -> NacosNamingService => registerInstance
思考: 为什么整合Nacos注册中心后,服务启动就会自动注册,Nacos是如何实现自动服务注册的?
-  Tomcat启动之后, 在ServletWebServerApplicationContext中,发布事件 ServletWebServerInitializedEvent 
-  spring-cloud-commons 包 AbstractAutoServiceRegistration 监听 WebServerInitializedEvent 
public abstract class AbstractAutoServiceRegistration<R extends Registration>
		implements AutoServiceRegistration, ApplicationContextAware,
		ApplicationListener<WebServerInitializedEvent> {
	public void onApplicationEvent(WebServerInitializedEvent event) {
		bind(event); // .... register();
	}
}
- Nacos 实现ServiceRegistry.register
Lifecycle Nacos 发布订阅 & Eureka 服务启动、同步、剔除
Lifecycle扩展场景——管理具有启动、停止生命周期需求的对象
start => AbstractApplicationContext.refresh -> finishRefresh() -> getLifecycleProcessor().onRefresh(); -> start()
整合Nacos 发布订阅 NacosWatch
public class NacosWatch
		implements ApplicationEventPublisherAware, SmartLifecycle, DisposableBean {
	@Override
	public 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());
		}
	}
}
整合Eureka 注册
扩展: Eureka Server端上下文的初始化是在SmartLifecycle#start中实现的
EurekaServerInitializerConfiguration
整合Ribbon
SmartInitializingSingleton扩展场景—— 对容器中的Bean对象进行定制处理
所有的单例bean实例化之后调用
思考:为什么@Bean修饰的RestTemplate加上@LoadBalanced就能实现负载均衡功能?
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}
LoadBalancerAutoConfiguration
 对SmartInitializingSingleton的扩展,为所有用@LoadBalanced修饰的restTemplate(利用了@Qualifier 限定符)绑定实现了负载均衡逻辑的拦截器LoadBalancerInterceptor
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
		final ObjectProvider<List<RestTemplateCustomizer>> 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 {
		@Bean
		public LoadBalancerInterceptor loadBalancerInterceptor(
				LoadBalancerClient loadBalancerClient,
				LoadBalancerRequestFactory requestFactory) {
			return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
		}
		@Bean
		@ConditionalOnMissingBean
		public RestTemplateCustomizer restTemplateCustomizer(
				final LoadBalancerInterceptor loadBalancerInterceptor) {
			return restTemplate -> {
				List<ClientHttpRequestInterceptor> list = new ArrayList<>(
						restTemplate.getInterceptors());
				list.add(loadBalancerInterceptor);
				restTemplate.setInterceptors(list);
			};
		}
	}
整合Feign
FactoryBean的扩展场景——将接口生成的代理对象交给Spring管理
思考:为什么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(); //
}
整合sentinel
HandlerInterceptor扩展场景——对mvc请求增强
AbstractSentinelInterceptor#preHandle
public abstract class AbstractSentinelInterceptor implements HandlerInterceptor {
    ...
    @Override
    public 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;
        }
    }
    ...
}
SmartInitializingSingleton&FactoryBean结合场景——根据类型动态装配对象
SentinelDataSourceHandler
#Sentinel持久化读数据源设计,利用了SmartInitializingSingleton扩展点
SentinelDataSourceHandler#afterSingletonsInstantiated
# 注册一个FactoryBean类型的数据源 
》SentinelDataSourceHandler#registerBean
》》NacosDataSourceFactoryBean#getObject
# 利用FactoryBean获取到读数据源
》》new NacosDataSource(properties, groupId, dataId, converter)
NacosDataSourceFactoryBean
public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource> {
	...
	@Override
	public NacosDataSource getObject() throws Exception {
		...
		return new NacosDataSource(properties, groupId, dataId, converter);
	}
	...
}
SentinelDataSourceHandler
public class SentinelDataSourceHandler implements SmartInitializingSingleton {
	...
	@Override
	public void afterSingletonsInstantiated() {
		...
		//sentinel.nacos.config.serverAddr=${sentinel.nacos.config.serverAddr}
		//NacosDataSource
		AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties.getValidDataSourceProperties();
		abstractDataSourceProperties.setEnv(env);
		abstractDataSourceProperties.preCheck(dataSourceName);
		registerBean(abstractDataSourceProperties, dataSourceName+ "-sentinel-" + validFields.get(0) + "-datasource"); //NacosDataSource
		...
	}
	...
}
整合seata (Spring Aop)
AbstractAutoProxyCreator&MethodInterceptor结合场景——实现方法增强
GlobalTransactionScanner

GlobalTransactionalInterceptor

public class GlobalTransactionalInterceptor implements ConfigurationChangeListener, MethodInterceptor, SeataInterceptor {
	...
    @Override
    public 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 transactionInfo
        TransactionInfo 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 transaction
                    break;
                case SUPPORTS:
                    // If transaction is not existing, execute without transaction.
                    if (notExistingTransaction(tx)) {
                        return business.execute();
                    }
                    // Continue and execute with new transaction
                    break;
                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 holder
            GlobalLockConfig 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 Business
                    rs = 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. clear
                resumeGlobalLockConfig(previousConfig);
                triggerAfterCompletion();
                cleanUp();
            }
        } finally {
            // If the transaction is suspended, resume it.
            if (suspendedResourcesHolder != null) {
                tx.resume(suspendedResourcesHolder);
            }
        }
    }
}


![[附源码]java毕业设计养老院管理系统](https://img-blog.csdnimg.cn/b69d6fffdcd5404ab81c3ef14f73c569.png)
















