`

(转)spring beans源码解读之--Bean的注解(annotation)

 
阅读更多

随着spring注解的引入,越来越多的开发者开始使用注解,这篇文章将对注解的机制进行串联式的讲解,不求深入透彻,但求串起spring beans注解的珍珠,展示给大家。

1. spring beans常用的注解:

  public @interface Autowired:可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。

复制代码
Marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities.
Only one constructor (at max) of any given bean class may carry this annotation, indicating the constructor to autowire when used as a Spring bean. Such a constructor does not have to be public.

Fields are injected right after construction of a bean, before any config methods are invoked. Such a config field does not have to be public.

Config methods may have an arbitrary name and any number of arguments; each of those arguments will be autowired with a matching bean in the Spring container. Bean property setter methods are effectively just a special case of such a general config method. Such config methods do not have to be public.

In the case of multiple argument methods, the 'required' parameter is applicable for all arguments.

In case of a Collection or Map dependency type, the container will autowire all beans matching the declared value type. In case of a Map, the keys must be declared as type String and will be resolved to the corresponding bean names.

Note that actual injection is performed through a BeanPostProcessor which in turn means that you cannot use @Autowired to inject references into BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation).

Since:
2.5
复制代码

  public @interface Configurable @Configurable 注解中的autowire属性就可以让Spring来自动装配了: @Configurable(autowire=Autowire.BY_TYPE) 或者 @Configurable(autowire=Autowire.BY_NAME,这样就可以按类型或者按名字自动装配了。

Marks a class as being eligible for Spring-driven configuration.
Typically used with the AspectJ AnnotationBeanConfigurerAspect.

Since:
2.0
public @interface Value:用于注入SpEL表达式,可以放置在字段方法或参数上。
复制代码
Annotation at the field or method/constructor parameter level that indicates a default value expression for the affected argument.
Typically used for expression-driven dependency injection. Also supported for dynamic resolution of handler method parameters, e.g. in Spring MVC.

A common use case is to assign default field values using "#{systemProperties.myProp}" style expressions.

Note that actual processing of the @Value annotation is performed by a BeanPostProcessor which in turn means that you cannot use @Value within BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation).

Since:
3.0
复制代码
public @interface Qualifier:指定限定描述符,对应于基于XML配置中的<qualifier>标签,@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者
@Qualifier(value = "限定标识符") 。
This annotation may be used on a field or parameter as a qualifier for candidate beans when autowiring. It may also be used to annotate other custom annotations that can then in turn be used as qualifiers.
Since:
2.5
public @interface Required 依赖检查;
复制代码
Marks a method (typically a JavaBean setter method) as being 'required': that is, the setter method must be configured to be dependency-injected with a value.
Please do consult the javadoc for the RequiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation).

Since:
2.0

 

复制代码

2. 注解bean的定义AnnotatedBeanDefinition

复制代码
public interface AnnotatedBeanDefinition extends BeanDefinition {

    /**
     * Obtain the annotation metadata (as well as basic class metadata)
     * for this bean definition's bean class.
     * @return the annotation metadata object (never {@code null})
     */
    AnnotationMetadata getMetadata();

}
复制代码

   该接口继承了BeanDefinition,提供了一个getMetadata()方法来获取该bean definition的注解元数据。

其中,AnnotationMetadata定义了访问特定类的注解的抽象接口,它不需要加载该类即可访问。

public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
}
ClassMetadata定义了一个特定类的抽象元数据,不需要加载此类。主要方法如下:
String getClassName()返回该类的名称。boolean isInterface()返回该类是否是接口。boolean isAbstract()返回该类是否为抽象类。boolean isConcrete()返回该类是否为具体类。boolean isFinal()返回该类是否为final类boolean hasSuperClass()返回该类是否有父类
String getSuperClassName()返回父类的名称,没有的话返回null.
String[] getInterfaceNames()返回继承的接口数组,如果没有,返回空.
String[] getMemberClassNames()返回引用的类的名称。

AnnotatedTypeMetadata定义访问特定类型的注解,不需要加载类。主要方法有:

boolean isAnnotated(String annotationType)是否有匹配的注解类型
Map<String,Object> getAnnotationAttributes(String annotationType,boolean classValuesAsString)获取特定类型注解的属性

AnnotationMetadata的标准实现类StandardAnnotationMetadata,它使用标准的反射来获取制定类的内部注解信息。主要方法有:

getAllAnnotationAttributes(String annotationType) 
getAnnotatedMethods(String annotationType) 
hasMetaAnnotation(String annotationType) 
isAnnotated(String annotationType) 
hasAnnotatedMethods(String annotationType) 

AnnotationMetadata还有一个子类:AnnotationMetadataReadingVisitor,它是字节码访问实现。

class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata {
}

让我们了解一下visitor模式:

定义:

The Gang of Four defines the Visitor as: "Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates."—″≤

The nature of the Visitor makes it an ideal pattern to plug into public APIs thus allowing its clients to perform operations on a class using a “visiting” class without having to modify the source.

uml 结构图如下:

<iframe id="iframe_0.3630733445752412" style="box-sizing: border-box; border-width: initial; border-style: none; width: 300px; height: 267px;" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/VisitorDiagram.svg/300px-VisitorDiagram.svg.png?_=4199459%22%20style=%22border:none;max-width:1611px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.3630733445752412',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>

 小结:vistor设置模式把状态抽象出来成为一个接口(访问者),不同的状态就作为状态的不同实现类(不同的访问者)。

 3. 注解bean的实现类

    3.1 AnnotatedGenericBeanDefinition

          继承了GenericBeanDefinition,增加了对注解元素的支持,这种支持是通过AnnotationBeanDefinition暴露的的注解元素接口。

    GenericBeanDefinition主要用来测试AnnotatedBeanDefinition上的操作的,例如:在spring的component扫描支持的实现中(默认实现类是ScannedGenericBeanDefinition,它同样实现了AnnotatedBeanDefinition接口)

  3.2 ConfigurationClassBeanDefinition

    ConfigurationClassBeanDefinition是ConfigurationClassBeanDefinitionReader的内部类,ConfigurationClassBeanDefinitionReader读取一组完全填充了属性的配置实例,通过context内给定的BeanDefinitionRegistry进行注册bean definition。这个类在BeanDefinitionReader这层后就改造,但没有继承或者扩展配置类。

   3.3 ScannedGenericBeanDefinition

   基于asm的类解析器,是GenericBeanDefinition类的扩展,支持注解元数据,这种支持通过AnnotatedBeanDefinition接口实现。

4. 注解的解析与处理

4.1 @Autowired注解实现AutowiredAnnotationBeanPostProcessor

   

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
}
AutowiredAnnotationBeanPostProcessor 间接继承了BeanPostProcessor,它自动绑定注解的field,setter方法和任意的配置方法。当检测到5个java注解时这些成员被注入其中。spring默认的注解为@Autowired和@Value。
另外:也支持JSR-330的@inject注解,作为@Autowired的替代方案。

当制定bean 类的唯一构造方法带有required 注解参数,且required值设置为true时,表明当作为spring一个bean时,构造方法默认自动绑定。若多个构造方法带有non-required 注解参数,它们将作为自动绑定的候选项。带有大量依赖的构造方法可以通过spring容器中的匹配的bean来构造,如果没有候选者满足条件,则会使用默认的构造器。注解构造器不一定是public的。
Field注入是在构造方法之后,配置方法之前,这种配置field不要求一定为public
配置方法可以有任意的名称和不定的参数列表,这些参数则被自动注入到spring容器中的匹配的bean。bean的属性setter方法仅仅是通用的配置方法的一个特例而已。配置方法不要求方法一定为public
注意:默认注册AutowiredAnnotationBeanPostProcessor的方式有<context:annotation-config> 和<context:component-scan> xml标签,如果你指定了一个自定义的AutowiredAnnotationBeanPostProcessor bean definition,移除或者关闭默认的注解配置。
其中,MergedBeanDefinitionPostProcessor的定义如下:
复制代码
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

    /**
     * Post-process the given merged bean definition for the specified bean.
     * @param beanDefinition the merged bean definition for the bean
     * @param beanType the actual type of the managed bean instance
     * @param beanName the name of the bean
     */
    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

}
复制代码
BeanPostProcessor 是一个可以定制修改一个新的bean实例的工厂钩子,例如:检查marker接口或者使用代理包装他们。
applicationContext可以在他们的bean容器中自动识别BeanPostProcessor bean,并将它们应用到接下来所创建的bean。一般的bean factory通过编程来注册Post-processor,并将它们应用到整个bean factory创建bean的过程中。

通常意义上,post-processor 设置bean属性通过marker 接口或者类似于实现postProcessBeforeInitialization(java.lang.Object, java.lang.String);使用代理包装bean通常实现postProcessAfterInitialization(java.lang.Object, java.lang.String).

4.2 @configurable注解实现AnnotationBeanWiringInfoResolver 

设置 @Configurable 注解中的autowire属性就可以让Spring来自动装配了: @Configurable(autowire=Autowire.BY_TYPE) 或者 @Configurable(autowire=Autowire.BY_NAME,这样就可以按类型或者按名字自动装配了。

    AnnotationBeanWiringInfoResolver 继承自BeanWiringInfoResolver,BeanWiringInfoResolver使用configurable注解来查找哪些类需要自动绑定。

public class AnnotationBeanWiringInfoResolver implements BeanWiringInfoResolver {
}

实现了BeanWiringInfoResolver的resolveWiringInfo方法

复制代码
@Override
    public BeanWiringInfo resolveWiringInfo(Object beanInstance) {
        Assert.notNull(beanInstance, "Bean instance must not be null");
        Configurable annotation = beanInstance.getClass().getAnnotation(Configurable.class);
        return (annotation != null ? buildWiringInfo(beanInstance, annotation) : null);
    }

    /**
     * Build the BeanWiringInfo for the given Configurable annotation.
     * @param beanInstance the bean instance
     * @param annotation the Configurable annotation found on the bean class
     * @return the resolved BeanWiringInfo
     */
    protected BeanWiringInfo buildWiringInfo(Object beanInstance, Configurable annotation) {
        if (!Autowire.NO.equals(annotation.autowire())) {
            return new BeanWiringInfo(annotation.autowire().value(), annotation.dependencyCheck());
        }
        else {
            if (!"".equals(annotation.value())) {
                // explicitly specified bean name
                return new BeanWiringInfo(annotation.value(), false);
            }
            else {
                // default bean name
                return new BeanWiringInfo(getDefaultBeanName(beanInstance), true);
            }
        }
    }
复制代码

 4.3 @qualifier的注解实现类QualifierAnnotationAutowireCandidateResolver

 

public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
}

public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandidateResolver, BeanFactoryAware {
}

其中,AutowireCandidateResolver是一个策略接口,由它来决定特定的bean definition对特定的依赖是否可以作为一个自动绑定的候选项,它的主要方法有:

boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor)

Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor,String beanName)

Object getSuggestedValue(DependencyDescriptor descriptor)

 QualifierAnnotationAutowireCandidateResolver间接实现了AutowireCandidateResolver,对要自动绑定的field或者参数和bean definition根据@qualifier注解进行匹配。同时也支持通过@value注解来绑定表达式的值。

另外,还只是JSR-330的javax.inject.Qualifier注解。

4.4 @required注解实现类RequiredAnnotationBeanPostProcessor。

public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
}

和AutowiredAnnotationBeanPostProcessor一样,间接继承自BeanPostProcessor,它增加了对javaBean属性配置的约束,java 5 注解可以检测bean的required属性,spring默认是@Required注解。

注意:默认注册AutowiredAnnotationBeanPostProcessor的方式有<context:annotation-config> 和<context:component-scan> xml标签,如果你指定了一个自定义的
默认注册AutowiredAnnotationBeanPostProcessor的方式有<context:annotation-config> 和<context:component-scan> xml标签,如果你指定了一个自定义的AutowiredAnnotationBeanPostProcessor bean definition,移除或者关闭默认的注解配置。其余和AutowiredAnnotationBeanPostProcessor类似,不一一赘述了。

4.5 初始化和销毁方法的注解实现类InitDestroyAnnotationBeanPostProcessor

public class InitDestroyAnnotationBeanPostProcessor
        implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
}

InitDestroyAnnotationBeanPostProcessor间接继承了BeanPostProcess,实现了通过注解来初始化和销毁方法,是spring的InitializingBean和DisposableBean回调接口的注解实现。

它通过"initAnnotationType"和"destroyAnnotationType"属性来检查指定的注解类型,任何自定义的注解都可以使用。

初始化和销毁注解可以用在任意可见的方法:public,package-protected,protected,private等。尽管可以对多个方法进行注解,但我们推荐只在一个初始化和销毁方法上各自进行注解。

 

小结:

 Spring3的基于注解实现Bean依赖注入支持如下三种注解:
Spring自带依赖注入注解: Spring自带的一套依赖注入注解;
JSR-250注解:Java平台的公共注解,是Java EE 5规范之一,在JDK6中默认包含这些注解,从Spring2.5开始支持。
JSR-330注解:Java 依赖注入标准,Java EE 6规范之一,可能在加入到未来JDK版本,从Spring3开始支持;

其中,
Spring自带依赖注入注解

1 @Required:依赖检查;
2 @Autowired:自动装配2 
自动装配,用于替代基于XML配置的自动装配
基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器、字段、方法注入
3 @Value:注入SpEL表达式
用于注入SpEL表达式,可以放置在字段方法或参数上
@Value(value = "SpEL表达式")  
@Value(value = "#{message}")  
4 @Qualifier:限定描述符,用于细粒度选择候选者
@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者
@Qualifier(value = "限定标识符") 


JSR-250注解

1 @Resource:自动装配,默认根据类型装配,如果指定name属性将根据名字装配,可以使用如下方式来指定
@Resource(name = "标识符")  
字段或setter方法 

2 @PostConstruct和PreDestroy:通过注解指定初始化和销毁方法定义

 

JSR-330注解
1 @Inject:等价于默认的@Autowired,只是没有required属性
2 @Named:指定Bean名字,对应于Spring自带@Qualifier中的缺省的根据Bean名字注入情况
3 @Qualifier:只对应于Spring自带@Qualifier中的扩展@Qualifier限定描述符注解,即只能扩展使用,没有value属性

分享到:
评论

相关推荐

    清华大学DeepSeek从入门到精通(视频课程+PDF)

    【清华大学】DeepSeek从入门到精通(视频课程+PDF)

    更新-“双高计划”专业群完整申报书与建设方案/中期评估报告

    自2019年以来,教育部启动实施“双高计划”,遴选确定首批“双高计划”建设单位197所,其中高水平学校建设单位56所,高水平专业群建设单位141所,河南省有黄河水利职业技术学院、河南工业职业技术学院等6所职业学校入选。2022年,教育部开展国家“双高计划”中期绩效评价,从评价结果看,国家“双高计划”任务进展顺利,建设成效突出,形成了一批先进经验做法和典型案例,在引领职业教育改革、服务国家战略和支撑区域发展方面形成示范势头。 今天,我们给大家分享一些“双高计划”专业群完整申报书与建设方案和中期评估报告。 ## 一、专业群完整申报书与建设方案 ## 二、“双高计划”中期报告 (100多份)

    电子商务平台秒杀系统减库存设计的核心逻辑与优化策略解析

    内容概要:本文详细探讨了电商平台上秒杀系统中减库存的设计逻辑和技术优化方法。首先,文中阐述了‘下单减库存’、‘付款减库存’和‘预扣库存’三种常见方式及其各自面临的问题和局限性,尤其是面对高并发流量冲击下的系统稳定性与数据准确性保障挑战。接着讨论了适用于大规模促销活动中快速而精准地扣除存货的方法,提出了诸如应用本地缓存(Local Cache)、引入高性能持久化键值存储(如Redis),甚至修改数据库引擎源代码(InnoDB 层面排队机制)等一系列先进解决方案来确保交易流程顺畅。此外,还提到了在极端情况发生(例如超卖)时如何借助补救措施挽回损失的具体实例。 适合人群:电商平台开发运维技术人员;有兴趣深入了解电商业务架构和技术优化的开发者和IT管理人员。 使用场景及目标:①帮助设计师理解不同减库存策略的应用时机及其利弊;②指导程序员针对特定业务需求选择最适合的技术路径进行项目构建;③提供给运维专家关于改善在线交易平台响应速度和服务质量的专业见解。 其他说明:本篇文章对于构建高效的电子商贸系统有着极高的参考价值,尤其是那些准备应对瞬息万变市场环境下的企业来说尤为重要。它不仅限于理论探讨层面,

    动态表单,VUE动态表单 基于vue+elementplus实现动态表单组件,通过拖拽组件到面板即可实现一个表单 支持各个组件的动态隐藏显示,动态表格弹窗式维护

    动态表单,VUE动态表单。基于vue+elementplus实现动态表单组件,通过拖拽组件到面板即可实现一个表单。支持各个组件的动态隐藏显示,动态表格弹窗式维护。

    【毕业设计】java-springboot-vue家居日用小百货交易网站实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot-vue家居日用小百货交易网站实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue火锅店管理系统源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue火锅店管理系统源码(完整前后端+mysql+说明文档+LunW).zip

    基于springboot+vue的在线教育系统设计与实现(LW+PPT).zip

    随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了微服务在线教育系统的开发全过程。通过分析微服务在线教育系统管理的不足,创建了一个计算机管理微服务在线教育系统的方案。文章介绍了微服务在线教育系统的系统分析部分,包括可行性分析等,系统设计部分主要介绍了系统功能设计和数据库设计。 本微服务在线教育系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,课程信息管理,课程类型管理,学科管理,购买的课程管理,职业规划管理,视频点播管理,我的笔记管理,我的课程管理,消息通知管理,学习交流,试卷管理,留言板管理,试题管理,系统管理,考试管理。用户功能有个人中心,用户管理,购买的课程管理,我的笔记管理,我的课程管理,消息通知管理。因而具有一定的实用性。 本站是一个B/S模式系统,采用SSM框架,MYSQL数据库设计开发,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得微服务在线教育系统管理工作系统化、规范化。本系统的使用使管理人员从繁重的工作中解脱出来,实现无纸化办公,能够有效的提高微服务在线教育系统管理效率。 关键词:微服务在线教育系统;SSM框架;MYSQL数据库;Spring Boot

    基于Javascript实现,强化学习QLearning的一个贪吃蛇实例

    javascript 基于Javascript实现,强化学习QLearning的一个贪吃蛇实例.

    编程挑战_Chef卡牌游戏_学习资源_技能提升_1741399339.zip

    python教程学习

    基于springboot+vueIT技术交流和分享平台的设计与实现(LW).zip

    我国科学技术的不断发展,计算机的应用日渐成熟,其强大的功能给人们留下深刻的印象,它已经应用到了人类社会的各个层次的领域,发挥着重要的不可替换的作用。信息管理作为计算机应用的一部分,使用计算机进行管理,具有非常明显的优点,利用网络的优势特开发了本基于Spring Boot的IT技术交流和分享平台。 本IT技术交流和分享平台是基于Spring Boot框架,采用Java技术,MYSQL数据库进行开发的。系统具有灵活的一体化设计方式,圆满完成了整个系统的界面设计。本系统实现了用户功能模块和管理员功能模块两大部分,通过该系统用户可以快速进行IT技术交流和分享,管理员可登录系统后台对系统进行全面管理,确保系统正常稳定的运行。系统功能齐全,符合用户IT技术交流和分享的需求。 本文主要首先介绍了课题背景、设计原则和研究内容,系统采用的相关技术及开发平台,接着对本基于Spring Boot的IT技术交流和分享平台进行系统需求分析和设计,包括系统的功能模块,数据库的设计,系统结构以及系统界面设计等,最后对进行系统测试,完成本篇论文。 关键词:IT技术交流, Spring Boot框架, Java技术,MYSQL数据库

    疲劳检测yawn图片数据集

    疲劳检测yawn图片数据集

    JDK7通过java-jwt验证

    JDK7通过java-jwt验证

    【毕业设计】java-springboot+vue会议管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue会议管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    sksalahuddin2828_Python_1741398999.zip

    python学习资源

    51CTO 1、技术解析篇-DeepSeek入门宝典 2、开发实战篇-DeepSeek入门宝典 3、行业应用篇-DeepSeek入门宝典 4、个人使用篇-DeepSeek入门宝典

    51CTO 1、技术解析篇-DeepSeek入门宝典 2、开发实战篇-DeepSeek入门宝典 3、行业应用篇-DeepSeek入门宝典 4、个人使用篇-DeepSeek入门宝典

    机器学习与模式识别领域的PRML习题解析手册

    内容概要:本文档是由高正奇编辑的针对模式识别和机器学习(PRML)教科书的一份详细的解答手册。文档覆盖了从基本概念如误差函数求导、贝叶斯定理应用到多元高斯分布计算、Gamma函数积分及其性质等一系列复杂问题的解决方案,以及涉及线性模型分类的基础练习题、条件概率和联合概率计算等入门级习题。每一题都经过细致推导,帮助学生加深对机器学习相关概念的理解并掌握具体的数学方法。 适合人群:主要适用于正在攻读机器学习、模式识别相关课程的学生,以及从事数据科学工作的专业人士作为深入理解和实践指南。 使用场景及目标:本手册旨在辅助教学过程中遇到的具体难题解析,在研究和实践中作为参考资料进行理论验证和技术难点突破,尤其有助于准备考试或者项目实施时需要巩固知识的应用场合。 其他说明:书中题目涵盖广泛,既有直观的概率论应用,也有复杂的积分变换技巧和最优化思路展示,对于希望提高自身计算能力和解决实际问题能力的学习者非常有价值。但要注意的是,部分内容较为深奥,可能不适合初学者自学使用,最好配合课堂讲解或其他教材一起学习效果更佳。

    编程语言_Python_入门之旅_教程_1741403040.zip

    python学习资源

    RFID-MATLAB的高等数学-CH06.rar

    RFID-MATLAB的高等数学-CH06.rar

    spaceX Ship Flight Test 8

    spaceX 动力学分析

    基于springboot+vue的美容院管理系统(LW).zip

    如今的信息时代,对信息的共享性,信息的流通性有着较高要求,因此传统管理方式就不适合。为了让美容院信息的管理模式进行升级,也为了更好的维护美容院信息,美容院管理系统的开发运用就显得很有必要。并且通过开发美容院管理系统,不仅可以让所学的SpringBoot框架得到实际运用,也可以掌握MySQL的使用方法,对自身编程能力也有一个检验和提升的过程。尤其是通过实践,可以对系统的开发流程加深印象,无论是前期的分析与设计,还是后期的编码测试等环节,都可以有一个深刻的了解。 美容院管理系统根据调研,确定其实现的功能主要包括美容用品管理,美容项目管理,美容部位管理,销量信息管理,订单管理,美容项目预约信息管理等功能。 借助于美容院管理系统这样的工具,让信息系统化,流程化,规范化是最终的发展结果,让其遵循实际操作流程的情况下,对美容院信息实施规范化处理,让美容院信息通过电子的方式进行保存,无论是管理人员检索美容院信息,维护美容院信息都可以便利化操作,真正缩短信息处理时间,节省人力和信息管理的成本。 关键字:美容院管理系统,SpringBoot框架,MySQL

Global site tag (gtag.js) - Google Analytics