当前位置: 首页 > news >正文

【注解】Annotation Target ElementType

背景知识

Annotate、Annotation:注释、注解、批注、注

在java中,注解作为程序的元数据嵌入到程序当中,元数据标签的存在并不影响程序代码的编译和执行

所谓Annotation就是提供了一种为程序元素设置元数据的方法,可用于修 包、类、构造器、方法、成员变量、参数和局部变量具体详见元注解 Target的声明。 注解可以被一些解析工具或者是编译工具进行解析。 Annotat ion中的信息可以在编译、加载和运行时被读取(具体详见元注解 Retention ,并执行相应的处理。

当前许多java框架中大量使用注解,如Hibernate、Jersey、Spring。

什么是元数据 Metadata

元数据(Metadata),又称中介数据、中继数据,为 描述数据的数据(data about data),主要是 描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。

元数据是指 从信息资源中抽取出来的用于说明其特征、内容的结构化的数据(如题名、版本、出版数据、相关说明、检索点等),用于组织、描述、检索、保存、管理信息和知识资源。

任何文件系统中的数据都分为数据和元数据。数据是指普通文件中的实际数据,而元数据指用来描述一个文件的特征的系统数据,诸如访问权限、文件拥有者以及文件数据块的分布信息(inode…)等等。在集群文件系统中,分布信息包括文件在磁盘上的位置以及磁盘在集群中的位置。用户需要操作一个文件必须首先得到它的元数据,才能定位到文件的位置并且得到文件的内容或相关属性。

HTML的head里有一个meta标签。那么它是什么呢? 根据上面的解释,我们应该知道它是“关于文档的信息”了。meta的属性有两种,name和http-equiv,name属性用来描述网页的内容,http-equiv属性指示服务器在发送实际的文档之前先在要传送给浏览器的 MIME 文档头部包含名称/值对,比如用以说明主页制作所使用的文字以及语言。
以下为百度和新浪首页的meta标签:
//百度首页meta标签
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="referrer" content="always">
<meta name="theme-color" content="#2932e1">

//新浪首页部分meta标签
<meta name="keywords" content="新浪,新浪网,SINA,sina,sina.com.cn,新浪首页,门户,资讯" />
<meta name="description" content="新浪网为全球用户24小时提供全面及时的中文资讯,***。" />
<meta name="application-name" content="新浪首页"/>
基于元数据的广泛应用, JDK5.0引入了Annotation的概念来描述元数据

为什么要引入 Annotation

使用Annotation之前,XML被广泛的应用于描述元数据。不知何时开始一些应用开发人员和架构师发现XML的维护越来越糟糕了。他们希望使用一些和代码 紧耦合的东西,而不是像XML那样和代码是 松耦合的(在某些情况下甚至是完全分离的)代码描述。如果你在Google中搜索“XML vs. annotations”,会看到许多关于这个问题的辩论。最有趣的是 XML配置其实就是为了分离代码和配置而引入的。上述两种观点可能会让你很疑惑,两者观点似乎构成了一种循环,但各有利弊。下面我们通过一个例子来理解这两者的区别。

假如你想为应用设置 很多的常量或参数,这种情况下,XML是一个很好的选择,因为它不会同特定的代码相连。如果你想把 某个方法声明为服务,那么使用Annotation会更好一些,因为这种情况下需要注解和方法紧密耦合起来,开发人员也必须认识到这点。

另一个很重要的因素是 Annotation定义了一种标准的描述元数据的方式。在这之前,开发人员通常使用他们自己的方式定义元数据。例如,使用标记interfaces,注解,transient关键字等等。每个程序员按照自己的方式定义元数据,而不像Annotation这种标准的方式。

目前,许多框架将XML和Annotation两种方式结合使用,平衡两者之间的利弊。

XML 和 Annotation 的优缺点

目前 web 应用中几乎都使用 xml 作为配置项,xml 之所以这么流行,是因为它的很多优点是其它技术的配置所无法替代的。
xml的优点:
  • xml 作为可扩展标记语言最大的优势在于开发者能够为软件量身【定制】适用的标记,使代码更加通俗易懂。
  • 利用 xml 配置能使软件更具扩展性。例如 Spring 将 class 间的依赖配置在 xml 中,最大限度地提升应用的可扩展性。
  • 具有成熟的验证机制确保程序正确性。利用 Schema 或 DTD 可以对 xml 的正确性进行验证,避免了非法的配置导致应用程序出错。
  • 修改配置而无需变动现有程序

虽然有如此多的好处,但毕竟没有什么万能的东西,xml 也有自身的缺点。
xml的缺点:
  • 需要解析工具或类库的支持。
  • 解析 xml 势必会影响应用程序性能,占用系统资源。
  • 配置文件过多导致管理变得困难。
  • 编译期无法对其配置项的正确性进行验证,或要查错只能在运行期
  • IDE 无法验证配置项的正确性。
  • 查错变得困难,往往配置的一个手误导致莫名其妙的错误。
  • 开发人员不得不同时维护代码和配置文件,开发效率变得低下。
  • 配置项与代码间存在潜规则。改变了任何一方都有可能影响另外一方。

Annotation 的优点:
  • 保存在 class 文件中,降低维护成本。
  • 无需工具支持,无需解析。
  • 编译期即可验证正确性,查错变得容易
  • 提升开发效率。
Annotation的缺点:
  • 若要对配置项进行修改,不得不修改 Java 文件,重新编译打包应用。
  • 配置项编码在 Java 文件中,可扩展性差。

没有一个事物是万能的,同样 xml 和 java Annotation 都有各自的优缺点。且他们的优缺点恰恰是互补的,xml 的强项是 Annotation 所不具备的,而 Annotation 的优势也是 xml 所欠缺的。这也正是时下流行的 xml + Annotation 配置的原因所在。

注解的定义【重要】

定义一个Annotation类型使用【@interface】关键字,定义一个Annotation类型与定义一个接口非常像(只是多了一个@符号)。
public @interface TestAnnotation {
}
Annotation可以是上面的简单形式,还可以包含成员变量。

成员变量的一些规则
  • Annotation的成员变量以无形参的方法形式来声明,其方法名和返回值定义了该成员变量的名字和类型。
  • 使用带有属性的Annotation时,必须为其属性指定值,否则会报错。
  • 定义Annotation时可以使用【default】关键字为属性设置默认值,使用时可以不为该属性指定值(此时使用默认值)。
  • 如果Annotation中具有名为【value】的属性,在使用时如果只使用value属性的话,可以不写属性名直接指定值。
  • Annotation的属性类型只能是基本类型、String、enum、Class及上述类型的一维数组类型。
  • 对于数组类型,当数组中只有一个元素时,可以省略大括号。

案例

UserInfo
public @interface UserInfo {
	//Annotation中可以定义的属性类型只能是基本类型、String、enum、Class及上述类型的一维数组类型
	String username();//方法名定义了属性的名字(name),返回值定义了属性的类型,使用时必须为其所有定义的属性指定值(使用default的除外)

	String data() default "2017年9月2日";//可以使用default关键字为属性设置默认值,这样在使用时就可以不为该属性指定值

	int age();

	SexEnum sex();

	public static enum SexEnum {
		男, 女, 其他
	}
}
Citys
public @interface Citys {
	String username() default "包青天";

	String[] value();//如果Annotation中具有【名为value】的属性,在使用时如果【只使用value属性】的话,可以不写属性名直接指定值
}
使用
@UserInfo(age = 28, sex = UserInfo.SexEnum.男, username = "白乾涛")
public class Test {
	
	@Citys({ "广州", "深圳", "长沙", "呵呵", })  //后面支持带一个逗号,以方便扩展
	@UserInfo(age = 28, sex = UserInfo.SexEnum.男, username = "白乾涛", data = "2017.9.2 15:03")
	public static void main(String[] args) {
		
		@Citys(value = { "广州", "深圳", "长沙", "呵呵" }, username = "白乾涛")
		int i = 1;
	}

	@Citys("广州")
	String string = "只有一个元素时,可以省略大括号。此时后面不能带一个逗号,因为这种格式表明不会再扩展了";
}

四个元注解 meta-annotation

元注解的作用就是负责 注解其他注解。Java5.0定义了4个标准的 meta-annotation 类型,它们被用来提供 对其它 annotation 类型作说明(只能作用在注解上,不能作用在其他程序元素上)
Java5.0定义的四个元注解为: @Target     @Retention     @Documented      @Inherited
这些类型和它们所支持的类在 java.lang.annotation 包中可以找到。

Target 元素种类【重要】

Target 的完整定义
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface java.lang.annotation.Target {
    /**
     * @return an array of the kinds of elements an annotation type can be applied to
     */
    ElementType[] value();
}
指示 注解类型所适用的程序元素的种类
@Target用来限定一个Annotation可以用于修饰哪些程序元素(可修饰的程序元素由 ElementType 限定),例如方法、成员变量等。

如果注解类型声明中不存在 Target 元注解,则声明的类型可以用在 任一程序元素上;如果存在这样的元注解,则 编译器强制实施指定的使用限制。 
如上例中的 UserInfo,其可以作用到类(类是TYPE的一种)和方法(METHOD)上,所以用@Target来限定的话就是:
@Target(value = { ElementType.TYPE, ElementType.METHOD })
public @interface UserInfo { ... }
同样,用元注解@Target对注解Citys来限定的话就是:
@Target(value = { ElementType.METHOD, ElementType.LOCAL_VARIABLE, ElementType.FIELD })
public @interface Citys { ... }
如果一个注解使用 元注解【@Target(ElementType.ANNOTATION_TYPE)】来限定,则表明此注解只能用在注解类型元素的声明上,那么此注解就是一个元注解。实际上,四个元注解就是这么定义的:
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {...}

Retention 保留策略【重要】

Retention 的完整定义
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface java.lang.annotation.Retention {
    /**
     * @return the retention policy
     */
    RetentionPolicy value();
}
指示注解 类型的注解 要保留多久。如果注解 类型声明中不存在 Retention  注解 ,则保留策略默认为 RetentionPolicy.CLASS
注意,使用默认保留策略的注解,不能通过反射获取注解信息
只有元注解类型直接用于注解时,Target 元注解才有效。如果元注解类型用作另一种注解类型的成员,则无效。
四个元注解的定义都是【@Retention(RetentionPolicy.RUNTIME)】,也即编译器将把注解记录在类文件中,在运行时 VM 将保留注解,因此可以反射性地读取。

Documented 文档化

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface java.lang.annotation.Documented {
}
Indicates指示、表明、标志 that annotations with a type are to be documented by javadoc and similar tools by default.  This type should be used to annotate注释、注解、批注、注 the declarations声明、宣言、发表 of types whose annotations affect the use of annotated elements by their clients.  If a type declaration is annotated with Documented, its annotations become part of the public API of the annotated elements.
指示某一类型的注释将通过 javadoc 和类似的默认工具进行 文档化应使用此类型来注解这些类型的声明:其注解会影响由其客户端注解的元素的使用。 如果一个类型的声明是用 Documented 来注解的,则其注解将成为注解元素的 公共 API 的一部分。

效果测试
//@Documented
public @interface TestDocumented {
	String value();
}

@TestDocumented("白乾涛")
public class Test {
	@TestDocumented("白乾涛")
	public static void main(String[] args) {
	}
}
如果不加@Documented,默认情况下,javadoc是不包括注解的,此时生成的文档如下:

795730-20170903155333796-1001148214.png   795730-20170903155334093-1140888151.png
  如果声明注解时指定了 @Documented,则它就会被 javadoc 之类的工具处理,所以注解类型信息也会被包括在生成的文档中,此时生成的文档如下:
795730-20170903155334437-1111112855.png      795730-20170903155334749-677642502.png
其实没有什么卵用

Inherited 自动继承

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface java.lang.annotation.Inherited {
}
Indicates指示、表明、标志 that an annotation type is automatically inherited. If an Inherited meta-annotation is present存在 on an annotation type declaration, and the user queries查询 the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation. 
指示注解类型 被自动继承。如果在 注解类型声明中存在 Inherited 元 注解,并且用户在某一类声明中查询该 注解类型,同时该类声明中没有此类型的 注解,则将在该类的超类中自动查询该 注解类型。此过程会重复进行,直到找到此类型的 注解或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的 注解,则查询将指示当前类没有这样的 注解

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.
注意,如果使用 注解类型 注解类以外的任何事物,此元 注解类型都是无效的。还要注意,此元 注解仅促成从超类继承 注解;对已实现接口的 注解无效。

这是一个稍微复杂的注解类型,它指明被注解的类会自动继承。更具体地说,如果定义注解时使用了 @Inherited 标记,然后用定义的注解来标注另一个父类,父类又有一个子类,则 父类的所有属性将被继承到它的子类中

三个基本的注解

在 java.lang 包中提供了3个基本Annotation的用法,可以通过查看API文档来了解。

Override 重写

@Target(ElementType.METHOD)//可以看出,@Override只能修饰方法,不能修饰其他程序元素
@Retention(RetentionPolicy.SOURCE)
public @interface java.lang.Override {
}
表示 一个方法声明打算重写超类中的另一个方法声明 。如果方法利用此注释类型进行注解,但没有重写超类方法,则编译器会生成一条错误消息。

Deprecated 不赞成、废弃

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface java.lang.Deprecated {
}
A program element annotated @Deprecated is one that programmers are discouraged from using, typically because it is dangerous, or because a better alternative exists. Compilers warn when a deprecated program element is used or overridden in non-deprecated code.
使用@Deprecated 注释的程序元素,是不鼓励 程序员使用的元素, 通常是因为它很危险或存在更好的选择。  在使用不被赞成的程序元素,或在不被赞成的代码中执行重写时,编译器会发出警告。

SuppressWarnings 压制警告

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface java.lang.SuppressWarnings {
    /**
     * @return the set of warnings to be suppressed
     */
    String[] value();
}
Indicates that the named compiler warnings指定的编译器警告 should be suppressed压制、取消 in the annotated element (and in all program elements contained in the annotated element). 
指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中,取消显示指定的编译器警告。

Note that the set of warnings suppressed in a given element is a superset of the warnings suppressed in all containing elements. For example, if you annotate a class to suppress one warning and annotate a method to suppress another, both warnings will be suppressed in the method. 
注意,在给定元素中取消显示的警告集,是所有包含元素中取消显示的警告的超集。例如,如果注释一个类来取消显示某个警告,同时注释一个方法来取消显示另一个警告,那么将在此方法中同时取消显示这两个警告。

As a matter of style, programmers should always use this annotation on the most deeply nested element where it is effective有效. If you want to suppress a warning in a particular特定的 method, you should annotate that method rather than its class.
根据风格不同,程序员应该始终 在最里层的嵌套元素上使用此注释,在那里使用才有效。例如,如果要在特定的方法中取消显示某个警告,则应该注释该方法而不是注释它的类。

两个相关的枚举

ElementType 元素类型【重要】

public enum java.lang.annotation.ElementType extends Enum<ElementType>
程序元素类型。此枚举类型的常量提供了 Java 程序中声明的元素的简单分类。
这些常量与 Target 元注解类型一起使用,以指定在什么情况下使用注解类型是合法的。

枚举常量
  1. ANNOTATION_TYPE  注解类型声明
  2. CONSTRUCTOR  构造方法声明
  3. FIELD  字段声明(包括枚举常量)
  4. LOCAL_VARIABLE   局部变量声明
  5. METHOD  方法声明
  6. PACKAGE  包声明
  7. PARAMETER  参数声明
  8. TYPE  类、接口(包括注解类型)或枚举声明
  9. TYPE_PARAMETER    @since 1.8
  10. TYPE_USE    @since 1.8

方法
  • static ElementType    valueOf(String name)   返回带有指定名称的该类型的枚举常量。
    • 字符串必须与用于声明该类型的枚举常量的 标识符 完全匹配(不允许有多余的空格,大小写敏感)
    • 如果该枚举类型没有带有指定名称的常量, - 则抛出 IllegalArgumentException
  • static ElementType[]    values()  Returns an array containing the constants of this enum type, in the order they are declared.
System.out.println(ElementType.values().length);//10
for (ElementType c : ElementType.values()) {
    System.out.print(c + "  ");//TYPE  FIELD  METHOD  PARAMETER  CONSTRUCTOR
    //LOCAL_VARIABLE  ANNOTATION_TYPE  PACKAGE  TYPE_PARAMETER  TYPE_USE  
}
System.out.println(ElementType.valueOf("FIELD"));//FIELD

RetentionPolicy 保留策略

public enum java.lang.annotation.RetentionPolicy extends Enum<RetentionPolicy>
注解 保留策略。此枚举类型的常量描述保留注解的不同策略。它们与 Retention 元注解类型一起使用,以指定保留多长的注解。

枚举常量
  • CLASS  在class文件中有效。编译器将把注解记录在类文件中,但在运行时 VM 不需要保留注解。这是默认的行为。也就是说,默认行为是:当运行Java程序时,JVM不可获取Annotation信息。
  • RUNTIME  在运行时有效。编译器将把注解记录在类文件中,在运行时 VM 将保留注解,因此可以反射性地读取
  • SOURCE  只在源文件中有效。编译器要丢弃的注解

方法
  • static RetentionPolicy    valueOf(String name)   返回带有指定名称的该类型的枚举常量。
    • 字符串必须与用于声明该类型的枚举常量的 标识符 完全匹配(不允许有多余的空格,大小写敏感)。
    • 如果该枚举类型没有带有指定名称的常量, - 则抛出 IllegalArgumentException
  • static RetentionPolicy[]    values()  Returns an array containing the constants of this enum type, in the order they are declared.
System.out.println(RetentionPolicy.values().length);//3
for (RetentionPolicy r : RetentionPolicy.values()) {
    System.out.print(r + "  ");//SOURCE  CLASS  RUNTIME  
}
System.out.println(RetentionPolicy.valueOf("CLASS"));//CLASS

附加:Annotation 注解的公共接口

public interface java.lang.annotation.Annotation 
The common interface extended by all annotation types. Note that an interface that manually extends this one does not define an annotation type. Also note that this interface does not itself define an annotation type. 
所有 annotation 类型都要扩展的公共接口。注意,手动扩展该公共接口的接口不 定义 annotation 类型。还要注意此接口本身不定义 annotation 类型。

More information about annotation types can be found in section 9.6 of The Java™ Language Specification. The java.lang.reflect.AnnotatedElement interface discusses compatibility兼容性 concerns when evolving an annotation type from being non-repeatable to being repeatable.
有关注解类型的更多信息,请参见 Java™语言规范第9.6节。 java.lang.reflect.AnnotatedElement接口讨论了,将 注解类型从不可重复转变为可重复时的,兼容性问题。

所有已知实现类:
BindingType, ConstructorProperties, Deprecated, DescriptorKey, Documented, Generated, HandlerChain, Inherited, InitParam, MXBean, Oneway, Override, PostConstruct, PreDestroy, RequestWrapper, Resource, Resources, ResponseWrapper, Retention, ServiceMode, SOAPBinding, SOAPMessageHandler, SOAPMessageHandlers, SupportedAnnotationTypes, SupportedOptions, SupportedSourceVersion, SuppressWarnings, Target, WebEndpoint, WebFault, WebMethod, WebParam, WebResult, WebService, WebServiceClient, WebServiceProvider, WebServiceRef, WebServiceRefs, XmlAccessorOrder, XmlAccessorType, XmlAnyAttribute, XmlAnyElement, XmlAttachmentRef, XmlAttribute, XmlElement, XmlElementDecl, XmlElementRef, XmlElementRefs, XmlElements, XmlElementWrapper, XmlEnum, XmlEnumValue, XmlID, XmlIDREF, XmlInlineBinaryData, XmlJavaTypeAdapter, XmlJavaTypeAdapters, XmlList, XmlMimeType, XmlMixed, XmlNs, XmlRegistry, XmlRootElement, XmlSchema, XmlSchemaType, XmlSchemaTypes, XmlTransient, XmlType, XmlValue

方法
  • boolean    equals(Object obj) 
  • int    hashCode() 
  • String    toString()  返回此 annotation 的字符串表示形式。
    • 表示形式的细节取决于实现,但下面的情况是最常见的【@com.bqt.Citys(username=包青天, value=[广州, 深圳])
  • Class<? extends Annotation>    annotationType()  返回此 annotation 的注解类型。
@Citys({ "广州", "深圳", })//必须设置保留策略为【@Retention(RetentionPolicy.RUNTIME)】才能通过反射获取注解信息

Citys ann = method.getAnnotation(Citys.class);
System.out.println(ann.username() + "  " + Arrays.toString(ann.value()) + "  " + ann.annotationType());//包青天  [广州, 深圳]  interface com.bqt.Citys
System.out.println(ann.toString());//@com.bqt.Citys(username=包青天, value=[广州, 深圳])
2017-9-3


来自为知笔记(Wiz)


相关文章:

  • docker compose 服务启动顺序控制
  • 《中国人工智能学会通讯》——1.39 结 论
  • win7旗舰版(可能是盗版^.^)开机提示准备桌面,进入桌面变了
  • CeBIT 2016不得不看之:中兴通讯不断成熟的‘智慧城市’
  • 使用C#生成随机密码(纯数字或字母)和随机卡号(数字与字母组合)
  • 曼迪安特警告:思科商业路由固件被感染
  • nginx 重定向浏览器url跳转和不跳转两种需求
  • 《中国人工智能学会通讯》——4.19 粒计算与不确定性
  • 分页技术关键代码(java连接mysql)
  • python地址解析经纬度,城市
  • 前端攻城师
  • python学习之老男孩python全栈第九期_day027知识点总结——反射、类的内置方法
  • 我的KT库之-----认识KT
  • 深度学习将成为中国监控市场增长的新引擎
  • Android 开源框架 ( 八 ) 注解框架---ButterKnife
  • JavaScript HTML DOM
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JavaScript学习总结——原型
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • uni-app项目数字滚动
  • webpack4 一点通
  • Yii源码解读-服务定位器(Service Locator)
  • 从输入URL到页面加载发生了什么
  • 大数据与云计算学习:数据分析(二)
  • 记一次删除Git记录中的大文件的过程
  • 面试遇到的一些题
  • 前嗅ForeSpider采集配置界面介绍
  • 数据可视化之 Sankey 桑基图的实现
  • 推荐一个React的管理后台框架
  • 小而合理的前端理论:rscss和rsjs
  • 正则表达式小结
  • ​业务双活的数据切换思路设计(下)
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • $(function(){})与(function($){....})(jQuery)的区别
  • (2.2w字)前端单元测试之Jest详解篇
  • (AngularJS)Angular 控制器之间通信初探
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (多级缓存)缓存同步
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)计算机毕业设计大学生兼职系统
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (未解决)macOS matplotlib 中文是方框
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Core 和 .NET Framework 中的 MEF2
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET 使用 XPath 来读写 XML 文件
  • .NET简谈设计模式之(单件模式)
  • .net开发引用程序集提示没有强名称的解决办法
  • :如何用SQL脚本保存存储过程返回的结果集
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用