前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文带你看懂:不为人知的 package-info.java 文件

一文带你看懂:不为人知的 package-info.java 文件

作者头像
后台技术汇
发布2022-05-30 09:41:36
1.4K0
发布2022-05-30 09:41:36
举报
文章被收录于专栏:后台技术汇

许多同学日常开发时,都不太注意到,原来自己维护这么久的 web 工程中,居然还有 package-info.java 这么一个类。

但只要我们在 idea 中搜索一下,就能够发现很多依赖包,都用到了这个类的实现。

那么,下面我们一起研究下,到底什么是 package-info.java 类文件~~

【目录】

1)注解技术

2)package-info类拆解

3)动态ClassLoader原理 与 双亲委派机制

4)自定义ClassLoader

一、注解技术

注解(annotation)是 Java 5 引入的,用来为类、方法、字段、参数等 Java 结构提供额外信息的机制。我先举个例子,比如,Java 核心类库中的@Override注解是被用来声明某个实例方法重写了父类的同名同参数类型的方法。

代码语言:javascript
复制
package java.lang;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

二、package-info类拆解

下面我们用一个简单的例子(分包逻辑开发),演示 package-info.java 的用法:

1)创建一个package:packageinfo

2)创建一个注解:PackageAnotation

代码语言:javascript
复制

/**
 * PackageAnotation.java 定义修饰包的注解
 * <b>package-info不是平常类,其作用有三个:</b><br>
 * 1、为标注在包上Annotation提供便利;<br>
 * 2、声明包的私有类和常量;<br>
 * 3、提供包的整体注释说明。<br>
 */
@Target(ElementType.PACKAGE)
@Retention(RetentionPolicy.RUNTIME)
@interface PackageAnotation {
  public String version() default "";
}

3)创建一个类,类名 = package-info.java

代码语言:javascript
复制

/**
 * <b>package-info不是平常类,其作用有三个:</b><br>
 * 1、为标注在包上Annotation提供便利;<br>
 * 2、声明包的私有类和常量;<br>
 * 3、提供包的整体注释说明。<br>
 */
@PackageAnotation(version="1.0")
package packageinfo;

4)创建测试用例,类名 = TestPackageInfo.java

代码语言:javascript
复制
package packageinfo;

/**
 * 测试package-info.java文件的作用
 * 1、为标注在包上Annotation提供便利;<br>
 * 2、声明包的私有类和常量;<br>
 * @author JoyoungZhang@gmail.com
 */
public class TestPackageInfo {
    public static void main(String[] args) {  
        //1 获取 Package 类
        Package p = Package.getPackage("packageinfo");
        //2 判断这个包对象,(是否在 package-info.java 中声明)且被某个注解(PackageAnotation)修饰
        if(p != null && p.isAnnotationPresent(PackageAnotation.class)) {
            //3 如果找到了注解,获取注解信息,实现业务逻辑(Servlet过滤、鉴权、分发请求等)
            PackageAnotation nav = p.getAnnotation(PackageAnotation.class);
            if (nav != null) {
                System.out.println("package version:" + nav.version());
            }
        }
    }
}

三、动态ClassLoader原理 与 双亲委派机制

3.1、动态ClassLoader原理

上面的测试用例,Package.getPackage("packageinfo"); 背后隐藏了一个原理 -- 类的动态加载。

写好一个Java程序,都是由若干个.class文件组织而成的一个完整的Java应用程序。当程序在运行时,即会调用该程序的一个入口函数,通过它来调用系统的相关功能;而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法。因此,如果另外一个文件不存在的,则会引发系统异常。而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是按需通过Java的类加载机制(ClassLoader)来动态加载某个class文件到内存当中的,从而只有class文件被载入到了内存之后,才能被其它class所引用。

所以ClassLoader就是用来动态加载class文件到内存当中用的。

我们写好的应用类(业务代码),大部分都是通过这个类加载器 AppClassLoader 来加载到JVM里面。

3.2 JVM默认有3个默认类加载器

3.2.1 AppClassLoader

AppClassLoader 称为应用类加载器,又称为系统类加载器,负责在JVM启动时,加载来自在命令java中的classpath或者java.class.path系统属性或者CLASSPATH操作系统属性所指定的JAR包和类路径。

3.2.2 ExtClassLoader

ExtClassLoader 称为扩展类加载器,主要负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包或者由java.ext.dirs系统属性指定的jar包.放入这个目录下的jar包对AppClassLoader加载器都是可见的(因为ExtClassLoader是AppClassLoader的父加载器,并且Java类加载器采用了委托机制)。

3.2.3 BootstrapClassLoader

BootstrapClassLoader 称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等,可通过如下程序获得该类加载器从哪些地方加载了相关的jar或class文件。

3.3 双亲委派机制

如果说,我们想引用一些外部依赖,那么就需要更高层的类加载器,让它们帮我们完成这个类装载的过程了,而这个过程也有个专有名词:双亲委派机制。

类加载分级:

-> 自定义ClassLoader

-> AppClassLoader

-> ExtClassLoader

-> BootstrapClassLoader

某个特定的类加载器在接到加载类的请求时,首先将加载任务委托交给父类加载器,父类加载器又将加载任务向上委托,直到最父类加载器,如果最父类加载器可以完成类加载任务,就成功返回,如果不行就向下传递委托任务,由其子类加载器进行加载。

总结

以上是关于package-info.java的相关知识介绍,还牵扯到了类加载器的回顾,希望对大家工作有所帮助。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后台技术汇 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3.2.1 AppClassLoader
  • AppClassLoader 称为应用类加载器,又称为系统类加载器,负责在JVM启动时,加载来自在命令java中的classpath或者java.class.path系统属性或者CLASSPATH操作系统属性所指定的JAR包和类路径。
  • 3.2.2 ExtClassLoader
  • 3.2.3 BootstrapClassLoader
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档