Spring5源码解析二

简介: //上面的是扫描普通的bean //处理@Import的3种情况(正常类;ImportSelector类;ImportBeanDefinitionRegistrar类) private void pr

//上面的是扫描普通的bean

//处理@Import的3种情况(正常类;ImportSelector类;ImportBeanDefinitionRegistrar类)
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,

        Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
    return;
}

if (checkForCircularImports && isChainedImportOnStack(configClass)) {
    this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
    this.importStack.push(configClass);
    try {
        for (SourceClass candidate : importCandidates) {
            if (candidate.isAssignable(ImportSelector.class)) {
                // Candidate class is an ImportSelector -> delegate to it to determine imports
                Class<?> candidateClass = candidate.loadClass();
                //反射实现一个对象
                ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                ParserStrategyUtils.invokeAwareMethods(
                        selector, this.environment, this.resourceLoader, this.registry);
                if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                    this.deferredImportSelectors.add(
                            new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                }
                else {
                    //回调
                    String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                    Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                    //递归,这里第二次调用processImports
                    //如果是一个普通类,会斤else
                    processImports(configClass, currentSourceClass, importSourceClasses, false);
                }
            }
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                // Candidate class is an ImportBeanDefinitionRegistrar ->
                // delegate to it to register additional bean definitions
                Class<?> candidateClass = candidate.loadClass();
                ImportBeanDefinitionRegistrar registrar =
                        BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                ParserStrategyUtils.invokeAwareMethods(
                        registrar, this.environment, this.resourceLoader, this.registry);
                //添加到一个list当中和importselector不同
                configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            }
            else {
                // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                // process it as an @Configuration class
                // 否则,加入到importStack后调用processConfigurationClass 进行处理
                //processConfigurationClass里面主要就是把类放到configurationClasses
                //configurationClasses是一个集合,会在后面拿出来解析成bd继而注册
                //可以看到普通类在扫描出来的时候就被注册了
                //如果是importSelector,会先放到configurationClasses后面进行出来注册
                this.importStack.registerImport(
                        currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                processConfigurationClass(candidate.asConfigClass(configClass));
            }
        }
    }
    catch (BeanDefinitionStoreException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanDefinitionStoreException(
                "Failed to process imports candidates for configuration class [" +
                configClass.getMetadata().getClassName() + "]", ex);
    }
    finally {
        this.importStack.pop();
    }
}

}


>processImports,处理import的类,主要是处理3种。
>1. 普通的bean
>2. 实现了 importSelector的bean(可以注册多个类的String数组字符串)
>3. 实现了ImportBeanDefinitionRegistrar

>1. import普通的bean,会先加入到importStack后调用processConfigurationClass 进行处理,放入到configurationClasses后面进行出来注册。
>2. import的是importSelector,会先实例化这个ImportSelector 类,然后执行该selector的selectImports方法,获取要注入到spring的bean工厂的类数组字符串,然后 对该String[]数组,进行再一次调用processImports方法处理,最终都是会进入到import普通bean的步骤,即:会先加入到importStack后调用processConfigurationClass 进行处理,放入到configurationClasses后面进行出来注册。
>3. import的是ImportBeanDefinitionRegistrar,会先实例化这个ImportBeanDefinitionRegistrar类,然后将它添加到一个list当中和importselector不同。

对于import的bean处理,是在 ConfigurationClassPostProcessor # processConfigBeanDefinitions()方法处理,即下面代码:

/**

  • 这里值得注意的是扫描出来的bean当中可能包含了特殊类

    • 比如ImportBeanDefinitionRegistrar那么也在这个方法里面处理
    • 但是并不是包含在configClasses当中
    • configClasses当中主要包含的是importSelector
    • 因为ImportBeanDefinitionRegistrar在扫描出来的时候已经被添加到一个list当中去了

    */

//bd 到 map 除却普通
this.reader.loadBeanDefinitions(configClasses);

//ConfigurationClassBeanDefinitionReader
public void loadBeanDefinitions(Set configurationModel) {

TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
    loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}

}

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的,会被spring标准
//早这里完成注册
if (configClass.isImported()) {
    registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//@Bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    loadBeanDefinitionsForBeanMethod(beanMethod);
}

 //xml
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

//注册Registrar
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

}

//将import和importSelector注入的bean,注册到bean工厂中
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {

AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);

if (logger.isDebugEnabled()) {
    logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}

}

//将ImportBeanDefinitionRegistrar注入的bean,注册到bean工厂中
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {

registrars.forEach((registrar, metadata) ->
        registrar.registerBeanDefinitions(metadata, this.registry));

}

> 总结:spring扫描类分了4种情况
> 1. 普通类,扫描到即刻注册到beanDefinitionMap中。
> 2. import(普通类),扫描到先存放到configurationClasses一个map集合。
> 3. import(importSelector),扫描到遍历循环一个一个的放到configurationClasses一个map集合。
> 4. import(importBeanDefinitionRegistrar),扫描到之后存放到importBeanDefinitionRegistrars一个map集合中。
> 备注:对于import的类,spring是在扫描之后,调用了loadBeanDefinitions方法将扫描到import的类注册到beanDefinitionMap中。

> full和lite的主要作用:
> 1. 当一个bean加了@Configuration注解,即是full全注解类。
> 2. 当一个bean加了@Component、@ComponentScan、@Import、@ImportResource等注解,即是lite
>备注:full全注解类,spring会为该类生成一个cglib代理类。

> 对于加了@Configuration注解的类,spring会对该类使用cglib产生一个代理类。
> 为什么需要使用cglib代理?
> > AppConfig类,使用@Bean注入了两个bean,在configDao2()方法中调用了configDao1()方法,这里就是为了防止configDao1对象被创建两次的问题。
> 
> 备注:cglib是基于继承的。
> 是在invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);方法执行的。

private static void invokeBeanFactoryPostProcessors(

        Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
//因为只有一条数据ConfigurationClassPostProcessor
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
    postProcessor.postProcessBeanFactory(beanFactory);
}

}

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
    throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
    // BeanDefinitionRegistryPostProcessor hook apparently not supported...
    // Simply call processConfigurationClasses lazily at this point then.
    processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
//给配置类产生cglib代理
//为什么需要产生cglib代理?(给AppConfig产生代理类,configDao2()方法调用了configDao1()方法)
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));

}

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {

Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
    BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
    //判断是否是一个全注解类
    //扫描是全注解类?full和lite的关系
    if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
        if (!(beanDef instanceof AbstractBeanDefinition)) {
            throw new BeanDefinitionStoreException("");
        }
        else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
            logger.warn("");
        }
        configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
    }
}
if (configBeanDefs.isEmpty()) {
    return;
}

//完成cglib代理
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
    AbstractBeanDefinition beanDef = entry.getValue();
    // If a @Configuration class gets proxied, always proxy the target class
    beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
    try {
        // Set enhanced subclass of the user-specified bean class
        Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
        if (configClass != null) {
            //完成对全注解类的cglib代理
            Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
            if (configClass != enhancedClass) {
                if (logger.isDebugEnabled()) {
                    logger.debug(""));
                }
                beanDef.setBeanClass(enhancedClass);
            }
        }
    }
}

}

ConfigurationClassEnhancer

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {

//判断是否被代理过
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
    if (logger.isDebugEnabled()) {
        logger.debug("");
    }
    return configClass;
}
//没有被代理cglib代理
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isDebugEnabled()) {
    logger.debug(String.format("");
}
return enhancedClass;

}

private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {

Enhancer enhancer = new Enhancer();
//增强父类,地球人都知道cglib是基于继承来的
enhancer.setSuperclass(configSuperClass);
//增强接口,为什么要增强接口?
//便于判断,表示一个类以及被增强了(实现BeanFactoryAware,为了获得BeanFactory对象)
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
//不继承Factory接口
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// BeanFactoryAwareGeneratorStrategy是一个生成策略
// 主要为生成的CGLIB类中添加成员变量$$beanFactory
// 同时基于接口EnhancedConfiguration的父接口BeanFactoryAware中的setBeanFactory方法,
// 设置此变量的值为当前Context中的beanFactory,这样一来我们这个cglib代理的对象就有了beanFactory
// 有了factory就能获得对象,而不用去通过方法获得对象了,因为通过方法获得对象不能控制器过程
// 该BeanFactory的作用是在this调用时拦截该调用,并直接在beanFactory中获得目标bean
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
//过滤方法,不能每次都去new
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;

}

//CALLBACK_FILTER:setCallbackFilter
private static final Callback[] CALLBACKS = new Callback[] {

    //增强方法,主要控制bean的作用域
    //(不用每一次都去调用new)
    new BeanMethodInterceptor(),
    //设置一个beanFactory
    new BeanFactoryAwareMethodInterceptor(),
    NoOp.INSTANCE

};
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);

/**

  • 用于拦截@Bean方法的调用,并直接从BeanFactory中获取目标bean,而不是通过执行方法。

*/
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
            MethodProxy cglibMethodProxy) throws Throwable {

    // enhancedConfigInstance 代理
    // 通过enhancedConfigInstance中cglib生成的成员变量$$beanFactory获得beanFactory。
    ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);

    String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

    // Determine whether this bean is a scoped-proxy
    Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
    if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
        String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
        if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
            beanName = scopedBeanName;
        }
    }
    
    if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
            factoryContainsBean(beanFactory, beanName)) {
        Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
        if (factoryBean instanceof ScopedProxyFactoryBean) {
            // Scoped proxy factory beans are a special case and should not be further proxied
        }
        else {
            // It is a candidate FactoryBean - go ahead with enhancement
            return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
        }
    }

    //一个非常牛逼的判断
    //判断到底是new 还是get
    //判断执行的方法和调用方法是不是同一个方法
    if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
        //如果是同一个方法:调用代理对象的方法,执行被代理类的方法(即configDao1()的new ConfigDao1()实例化configDao1对象)
        return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
    }
    //不是同一个方法:调用getBean方法。(即在执行configDao2()方法,调用了configDao1()方法)
    return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}

private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
        ConfigurableBeanFactory beanFactory, String beanName) {
    //判断他是否正在创建
    boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
    try {
        if (alreadyInCreation) {
            beanFactory.setCurrentlyInCreation(beanName, false);
        }
        boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
        if (useArgs && beanFactory.isSingleton(beanName)) {
            for (Object arg : beanMethodArgs) {
                if (arg == null) {
                    useArgs = false;
                    break;
                }
            }
        }
        //beanFactory.getBean
        //这个方法spring就写的非常牛逼,在bean实例化的会重点解析
        Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName));
        if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
            if (beanInstance.equals(null)) {
                if (logger.isDebugEnabled()) {
                    logger.debug(""));
                }
                beanInstance = null;
            }
            else {
                String msg = "";
                try {
                    BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
                    msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // Ignore - simply no detailed message then.
                }
                throw new IllegalStateException(msg);
            }
        }
        Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
        if (currentlyInvoked != null) {
            String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
            beanFactory.registerDependentBean(beanName, outerBeanName);
        }
        return beanInstance;
    }
    finally {
        if (alreadyInCreation) {
            beanFactory.setCurrentlyInCreation(beanName, true);
        }
    }
    
    //判断执行的方法和调用方法是不是同一个方法
    private boolean isCurrentlyInvokedFactoryMethod(Method method) {
        Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
        return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
                Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
    }
}

}

> 这里给加了@Configuration注解的类使用cglib动态代理产生的代理类:
>1. 主要是使用BeanMethodInterceptor类,在bean被实例化的时候,进行拦截。
>2. 怎么做到在configDao2()方法中调用了configDao1(),而configDao1没有被创建两次?
>>  主要是判断执行的方法和调用方法是不是同一个方法,即在执行configDao2()方法的时候,调用了configDao1()方法。
>>  所以在再次执行configDao1()方法时候,判断出发起调用的主方法是configDao2,即执行方法和调用方法不是同一方法。
>
>3.1 如果是同一个方法:调用代理对象的方法,执行被代理类的方法
>>       cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
>3.2 不是同一个方法:调用getBean方法
>>      return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
### spring初始化总结
#### spring的扩展点(5个)
>1. BeanPostProcessor
>>插手bean的实例过程、实例化之后,在bean没有被spring的bean容器管理之前干活。
>>经典场景:@PostConstruct、aop 
>2. BeanFactoryPostProcessor
>>spring的bean容器当中任意的一个bean被new出来之前执行,针对beanFactory来建设。
>>经典场景:ConfigurationClassPostProcessor#postProcessBeanFactory,针对配置类(@Configuration注解)加上cglib代理。
>3. BeanFactoryRegistryPostProcessor
>>是BeanFactoryPostProcessor的子类,在BeanFactoryPostProcessor之前执行?因为源码当中先遍历BeanFactoryRegistryPostProcessor(有spring提供的,还有自定义)自定义的先执行。
>>经典场景:ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry,扫描、3种import的扫描、@Bean的扫描,判断配置类是否是一个完整的配置类
>4. ImportSelector
>>通过这个方法selectImports返回一个类名(全名)数组,把他变成beanDefinition,动态添加beanDefinition(这个BeanDefinition是写死的,因为这个BeanDefinition是有spring内部生成的,我们无法改变这些BeanDefinition)
>5. ImportBeanDefinitionRegistrar
>>registerBeanDefinitions方法可以得到BeanDefinitionRegistry故而可以动态添加BeanDefinition,还可以改变BeanDefinition。
>>经典场景:mybatis的mapperScan

#### spring bean初始化结构图:
目录
相关文章
|
28天前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
14天前
|
缓存 安全 Java
Spring Security通用权限管理模型解析
Spring Security作为Spring生态的核心安全框架,结合RBAC与ACL权限模型,基于IoC与AOP构建灵活、可扩展的企业级权限控制体系,涵盖认证、授权流程及数据库设计、性能优化等实现策略。
79 0
|
14天前
|
缓存 安全 Java
Spring Security权限管理解析
Spring Security是Spring生态中的核心安全框架,采用认证与授权分离架构,提供高度可定制的权限管理方案。其基于过滤器链实现认证流程,通过SecurityContextHolder管理用户状态,并结合RBAC模型与动态权限决策,支持细粒度访问控制。通过扩展点如自定义投票器、注解式校验与前端标签,可灵活适配多租户、API网关等复杂场景。结合缓存优化与无状态设计,适用于高并发与前后端分离架构。
90 0
|
21天前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
28天前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
131 0
|
14天前
|
Java 数据库 数据安全/隐私保护
Spring Boot四层架构深度解析
本文详解Spring Boot四层架构(Controller-Service-DAO-Database)的核心思想与实战应用,涵盖职责划分、代码结构、依赖注入、事务管理及常见问题解决方案,助力构建高内聚、低耦合的企业级应用。
262 0
|
25天前
|
Kubernetes Java 微服务
Spring Cloud 微服务架构技术解析与实践指南
本文档全面介绍 Spring Cloud 微服务架构的核心组件、设计理念和实现方案。作为构建分布式系统的综合工具箱,Spring Cloud 为微服务架构提供了服务发现、配置管理、负载均衡、熔断器等关键功能的标准化实现。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
229 0
|
27天前
|
安全 Java 数据安全/隐私保护
Spring Security 核心技术解析与实践指南
本文档深入探讨 Spring Security 框架的核心架构、关键组件和实际应用。作为 Spring 生态系统中负责安全认证与授权的关键组件,Spring Security 为 Java 应用程序提供了全面的安全服务。本文将系统介绍其认证机制、授权模型、过滤器链原理、OAuth2 集成以及最佳实践,帮助开发者构建安全可靠的企业级应用。
88 0
|
2月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。

热门文章

最新文章

推荐镜像

更多
  • DNS