快讯 >

【编程开发】- 01 日志框架

2023-03-28 10:20:24   来源:腾讯云

日志实现框架

Log4j

Log4j是目前最为流行的Java日志框架之一,1999年发布首个版本,2012年发布最后一个版本,2015年正式宣布终止,官方也已不建议使用,并逐步被LogbackLog4j2等日志框架所替代,可是无法掩饰光辉历程,以及优良的设计理念。尽管Log4j有着出色的历史战绩,但早已不是Java日志框架的最优选择,还在使用该日志框架的项目往往是历史遗留问题。

Log4j API核心类:


(相关资料图)

日志对象:org.apache.log4j.Logger日志级别:org.apache.log4j.Level日志管理器:org.apache.log4j.LogManager日志仓储:org.apache.log4j.spi.LoggerRepository日志附加器:org.apache.log4j.Appender日志过滤器:org.apache.log4j.spi.Filter日志格式布局:org.apache.log4j.Layout日志事件:org.apache.log4j.LoggingEvent日志配置器:org.apache.log4j.spi.Configurator日志诊断上下文:org.apache.log4j.NDCorg.apache.log4j.MDC

JUL

Java LoggingJava标准的日志框架,也称为Java Logging API,即JSR 47。从Java 1.4版本开始,Java Logging成为Java SE的功能模块,其实现类存放在java.util.logging包下。

使用Java Logging最大好处是它属于JDK内置,不需要添加额外依赖,默认配置文件位于:jre/lib/logging.properties,具体可以查看LogManagerreadConfiguration方法,启动的时候可以通过设置VM参数java.util.logging.config.file指定配置文件。

Java Logging API核心类:

日志对象:java.util.logging.Logger日志级别:java.util.logging.Level日志管理器:java.util.logging.LogManager日志处理器:java.util.logging.Handler日志过滤器:java.util.logging.Filter日志格式器:java.util.logging.Formatter日志记录:java.util.logging.LogRecord日志权限:java.util.logging.LoggingPermission日志JMX接口:java.util.logging.LoggingMXBean

Logback

LogbackLog4j创始人设计的又一个开源日志框架,可以看成Log4j的替代者,在架构和特征上有着相当提升。Logback当前分成三个模块:

logback-core:其它两个模块的基础模块,提供一些关键的通用机制logback-classic:地位和作用等同于Log4j,也被认为是Log4j的一个改进版,并且实现了SLF4J APIlogback-accesslogback-access访问模块与TomcatJettyServlet容器集成配置Http访问的access日志

Logback核心类:

日志对象:ch.qos.logback.classic.Logger日志级别:ch.qos.logback.classic.Level日志管理器:ch.qos.logback.classic.LoggerContext日志附加器:ch.qos.logback.core.Appender日志过滤器:ch.qos.logback.core.filter.Filter日志格式布局:ch.qos.logback.core.Layout日志事件:ch.qos.logback.classic.spi.LoggingEvent日志配置器:ch.qos.logback.classic.spi.Configurator

核心架构

上图是logback日志框架的输出日志的核心流程:

Logger作为日志框架的代言人,程序开发通过Logger即可完成日志输出工作;Logger拿到程序传入的日志信息,通过Filter进行过滤,一般是对日志级别Level进行过滤,然后将符合条件的日志封装成LoggingEvent对象,并交接给关联的Appender对象进行后续处理;Appender完成日志输出工作,一般Appender也会有个Filter过滤流程,将过滤成功的日志输出到控制台、文件、网络等操作;

LoggerAppender是日志框架比较核心组件,Logger代表日志输入源,其配置样例见下:

Appender代表日志输出源,其配置样例见下:

LoggerAppender相互独立,都可以实现对日志过滤操作,同时可以实现多对多映射关系,在开发中可以对这些特性灵活应用。比如:生产中一个很常见的做法就是构建一个Level=ErrorAppender,然后让所有的Logger都指向该Appender就可以实现汇聚系统中所有Error级别的日志,可以快速监测系统运行是否出现异常状况。

Appender

节点被配置时,必须配置两个属性nameclassname指定Appender的名称,而class指定Appender具体的实现类。

Appender核心类结构图:

UnsynchronizedAppenderBase:非线程安全的Appender基类,即public void doAppend(E eventObject)没有使用synchronized关键字,而AppenderBase类中的doAppend()方法都使用了synchronized关键字:public synchronized void doAppend(E eventObject)

Level

日志可以分配级别,包括:ALLTRACEDEBUGINFOWARNERROROFF,其中ALLOFF日志级别是用于AppenderLogger过滤使用。

TRACE(追踪):输出更细致的程序运行轨迹;DEBUG(调试):这个级别一般记录一些运行中的中间参数信息,只允许在开发环境开启,选择性在测试环境开启;INFO(信息):用来记录程序运行中的一些有用的信息,例如:程序运行开始、结束、耗时、重要参数等信息,需要注意有选择性的有意义的输出,到时候自己找问题看一堆日志却找不到关键日志就没有意义了;WARN(警告):一般用来记录一些用户输入参数错误;ERROR(错误):一般用来记录程序中发生的任何异常错误信息(Throwable),或者是记录业务逻辑错误;

Logger

通过LoggerFactory获取LoggerLogger getLogger(String name)LoggerFactory采用工厂设计模式,内部维护一个Map缓存所有生成的Logger实例信息:Map loggerCache = new ConcurrentHashMap()

继承规则

Logger是有层次关系的,我们可一般性的理解为包名之间的父子继承关系。每个Logger通常以class全限名称为其名称。子Logger通常会从父Logger继承Logger级别Appender等信息。

统一日志API

日志框架无论Log4j还是Logback,虽然它们功能完备,但是各自API相互独立,并且各自为政。当应用系统在团队协作开发时,由于工程师人员可能有所偏好,因此,可能导致一套系统同时出现多套日志框架情况。

其次,最流行的日志框架基本上基于实现类编程,而非接口编程,因此,暴露一些无关紧要的细节给用户,这种耦合性是没有必要的。

诸如此类的原因,开源社区提供统一日志API框架,最为流行的是:

apache commons-logging:简称JCL,适配log4jjava loggingslf4j:适配log4jlog4j2java logginglogback

统一日志API,即日志门面接口层,直白点讲:提供了操作日志的接口,而具体实现交由LogbackLog4j等日志实现框架,这样就可以实现程序与具体日志框架间的解耦,对于底层日志框架的改变,并不影响到上层的业务代码,可以灵活切换日志框架。

日志体系

现在日志框架众多:slf4jjcljullog4jlog4j2logback等,它们之间存在什么样的关系,我们在开发过程中又如何选取这些日志框架呢?

首先,看下Java日志体系:

通过上图可以概括日志体系大致分为三层:日志接口门面层、绑定/桥接层以及日志实现层。

jcl-over-slf4j.jar(jcl -> slf4j):将commons-logging日志桥接到slf4jjul-to-slf4j.jar(jul -> slf4j):java.util.logging的日志桥接到slf4jlog4j-over-slf4j.jar(log4j -> slf4j):将log4j的日志,桥接到slf4jslf4j-log4j12.jar(slf4j -> log4j):slf4j绑定到log4j,所以这个包不能和log4j-over-slf4j.jar不能同时使用,会出现死循环slf4j-jcl.jar(slf4j -> jcl):slf4j绑定到commons-logging日志框架上slf4j-jdk14.jar(slf4j -> jul):slf4j绑定到jdk日志框架上,不能喝jul-to-slf4j.jar同时使用,会出现死循环slf4j-nop.jar:slf4j的空接口输出绑定,丢弃所有日志输出slf4j-simple.jar:slf4j自带的简单日志输出接口log4j-slf4j-impl.jar(slf4j -> log4j2):将slf4j绑定到log4j2日志框架上,不能和log4j-to-slf4j同时使用log4j-to-slf4j.jar(log4j2 -> slf4j):将log4j2日志桥接到slf4j上,不能和log4j-slf4j-impl同时使用

最为熟悉和使用率较高的log4j其实就位于日志实现层,即其为一种日志实现框架。既然log4j已经足够系统使用进行日志输出了,为啥还多此一举弄个日志接口门面层绑定/桥接层?看下图:

系统A集成了模块A模块B模块C三个模块,但是这三个模块使用了不同的日志实现框架,现在系统A相当于同时存在了三个日志框架,那如何进行配置呢?每个框架都构建一个配置文件这种肯定是不行的,没法进行统一管理,日志较为混乱。

现在看下如何解决上述问题:

模块A模块B模块C采用slf4j日志接口框架,而非具体日志实现类,具体使用哪种日志实现框架是由系统A配置决定的,系统Aslf4j绑定到logback,则统一采用logback日志框架,slf4j绑定到log4j则统一采用log4j日志框架。日志接口 --> 日志绑定 --> 日志实现,日志接口和日志实现进行了解耦,模块只关注接口不关注实现,具体采用哪种实现是由其所在的系统环境决定,这样就可以实现日志的统一配置和管理。

对于上述解决方案,如果模块A模块B模块C是新开发统一采用slf4j日志接口框架没问题,但是对于旧系统,比如模块B模块C都是很久之前开发的模块,分别采用了不同的日志实现框架,见下图:

如果系统Aslf4j绑定到logback日志框架上,但是模块B模块C由于没有采用slf4j,绑定对于它们来说是无效的,这时候就要使用桥接

桥接的大致结构如上图,通过桥接把log4jjdk log等日志实现框架桥接到slf4j上,由于slf4j又被绑定到了logback上,则模块B模块C最终会被logback纳管,而不是log4jjdk log,同样可以实现日志统一配置管理。

以上就是项目开发中经常遇到的问题,以及绑定和桥接之间的区别。

spring体系中日志框架

Spring框架

Spring Framework 4.X及之前的版本,都是使用的标准版JCL日志框架,该依赖由spring-core间接引入。Spring框架的日志信息都是使用JCL标准接口来进行输出。下面说下项目中常碰到的三种情况:

项目中使用log4jcommons-logging原生支持和log4j的动态绑定,所以不需要任何配置即可将jcl的日志输出绑定到log4j上;项目中使用log4j2commons-logging原生并不支持和log4j2的动态绑定,但是log4j2本身提供了将jcl绑定到log4j2的依赖包:log4j-jcl.jar;项目中使用slf4j:需要采用桥接模式jcl日志引入到SLF4J上,添加依赖包jcl-over-slf4j.jar,否则可能Spring框架的日志无法输出到日志文件中。

使用spring 4.X及之前版本的框架时一定要注意上面情况,否则很容易出现业务日志输出正常,但是spring框架本身日志没有输出的情况,导致一些错误无法察觉或者不利于排查。

spring5.0带来了commons-logging桥接模块的封装,它被叫做spring-jcl而不是标准版jcl,无需添加额外依赖包,可自动检测绑定到Log4j2SLF4J

SpringBoot框架

springboot-1.X- springboot-2.X:

SpringBoot框架可以看出,默认采用SLF4J+Logback组合的日志框架,通过桥接模式将其它日志框架桥接到SLF4J上。

SLF4J

SLF4J(Simple Logging Facade For Java)是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就像我们经常使用的JDBC一样,只是了一些标准规范接口。因此,单独的SLF4J是不能工作的,它必须搭配其他具体的日志实现方案。

SLF4JLogback是同一个作者开发的,所以Logback天然与SLF4J适配,不需要引入额外适配库。

这里还有个比较有意思的事情,SLF4J项目提供了很多适配库、桥接库,唯独没有提供对Log4j2的适配库和桥接库,不过Apache Logging项目组自己开发了:log4j-slf4j-impllog4j-to-slf4j

JCL

Jakarta commons-logging简称JCL,是apache提供的一个通用日志门面接口,最后版本更新停留在2014年,且默认只能提供对Log4jJava Logging进行适配。

JCL已慢慢淡出人们的视线,一些历史遗留项目也开始慢慢由JCL转向SLF4J,如:Spring 5.0开始没有再依赖原生的JCL框架,SpringBoot默认采用SLF4J+LogbackSLF4J已经成为了Java日志组件的明星选手,可以完美替代JCL,使用JCL桥接库也能完美兼容一切使用JCL作为日志门面的类库,现在的新系统已经没有不使用SLF4J作为统一日志API接口层的理由了。

核心原理

SLF4JJCL对比,二者最大区别在于它们的绑定机制的不同,这也决定了为什么JCL会被慢慢的淘汰掉的根本原因。

SLF4J绑定原理

1、slf4j定义好两个接口规范:

public interface LoggerFactoryBinder {    //获取一个ILoggerFactory实现类,采用工厂设计模式创建Logger    public ILoggerFactory getLoggerFactory();    public String getLoggerFactoryClassStr();}
public interface ILoggerFactory {    public Logger getLogger(String name);}

第一个接口LoggerFactoryBinder定义绑定类,如果日志框架需要和slf4j进行绑定,就要提供一个该接口实现类,并且名称是StaticLoggerBinder,这样,在slf4j模块中,使用StaticLoggerBinder.getSingleton();就可以获取到这个绑定类,进而通过StaticLoggerBinder绑定类的getLoggerFactory()获取到Logger生产工厂ILoggerFactory

注意:这里的绑定机制利用到了类加载原理,如果存在多个绑定类StaticLoggerBinder,根据类路径的前后顺序,只有有一个会被加载进来,这个加载进来的就实现了绑定。

2、ILoggerFactory也是slf4j模块提供的一个接口,因为各个日志框架中LoggerFactory不统一,所以slf4j提供一个接口,让各个日志框架把自己的LoggerFactory包装成ILoggerFactory接口,这样slf4j模块下就可以统一使用。这里利用到的是设计模式中的:适配模式。系统间对接比较常用的一种设计模式,系统间接口不统一,通过适配模式实现一致。

3、可以看下,slf4jlog4j绑定使用slf4j-log4j12.jar,这个模块下StaticLoggerBinder实现见下:

public class StaticLoggerBinder implements LoggerFactoryBinder {    private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();    public static final StaticLoggerBinder getSingleton() {        return SINGLETON;    }    public static String REQUESTED_API_VERSION = "1.6.99";     private static final String loggerFactoryClassStr = Log4jLoggerFactory.class.getName();    private final ILoggerFactory loggerFactory;    private StaticLoggerBinder() {        loggerFactory = new Log4jLoggerFactory();        try {            @SuppressWarnings("unused")            Level level = Level.TRACE;        } catch (NoSuchFieldError nsfe) {            Util.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");        }    }    public ILoggerFactory getLoggerFactory() {        return loggerFactory;    }    public String getLoggerFactoryClassStr() {        return loggerFactoryClassStr;    }}

4、StaticLoggerBinder:静态绑定,这个静态是相对于JCL所使用的动态绑定来说的,为什么说是静态的呢?因为你如果要绑定,需要在环境中添加绑定相关的jar,这样slf4j就可以加载到绑定包中的StaticLoggerBinder类实现绑定。

接口和实现类之间采用一种松耦合的设计,有利于灵活的扩展,但是在使用时有需要一种技术把它们关联起来,这是软件设计中比较常用到的设计思想,JDK 1.6对此专门提供了一种技术:SPISLF4J1.8版本起,也开始使用SPI方式实现绑定,而不再采用通过寻找指定类StaticLoggerBinder的方式进行绑定。下面代码就是slf4j-1.8中使用SPI进行绑定核心代码:

private static List findServiceProviders() {    ServiceLoader serviceLoader = ServiceLoader.load(SLF4JServiceProvider.class);    List providerList = new ArrayList();    for (SLF4JServiceProvider provider : serviceLoader) {        providerList.add(provider);    }    return providerList;}

SLF4JServiceProvider就是类似于上面的LoggerFactoryBinder接口,通过它可以获取到ILoggerFactory,这样其它日志框架和slf4j进行集成时只需要提供一个SLF4JServiceProvider接口的实现类即可,不再要求必须是像之前固定名称必须是:StaticLoggerBinder,固定名称带来的一个问题是包路径也要一致,无形中存在侵入性,而使用SPI方式更加的灵活。比如我们常用到的JDBC也使用到SPI,感兴趣的可以多了解下,对系统设计还是比较实用的一种技术。

JCL绑定原理

JCL采用动态绑定机制,缺点是容易引发混乱,在一个复杂甚至混乱的依赖环境下,确定当前正在生效的日志服务是很费力的,特别是在程序开发和设计人员并不理解JCL的机制时。

JCL动态绑定的核心逻辑位于LogFactoryImpl类的discoverLogImplementation方法中如下代码块:

for(int i=0; i

其中classesToDiscover数组的中定义了可以使用的适配器类,见下:

String[] classesToDiscover = {            "org.apache.commons.logging.impl.Log4JLogger",            "org.apache.commons.logging.impl.Jdk14Logger",            "org.apache.commons.logging.impl.Jdk13LumberjackLogger",            "org.apache.commons.logging.impl.SimpleLog"};

简单来说:JCL模块中会有判断,当前项目中是否存在Log4jAPI,如果有就直接和Log4j进行绑定;如果没有,则继续向下查找,是否存在JDK Log相关API,如果有就绑定;如果JDK Log也没有,则提供一个SimpleLog默认实现,该实现什么也不做,输出的日志直接会被丢弃,什么也看不到。

总结

相较于JCL动态绑定机制SLF4J则简单得多,采用静态绑定机制,可能你还没有很好理解这两者的本质区别,看下图:

JCL框架自动检查当前环境中是否存在相关日志API,如果有就绑定,注意它内部有个固定的绑定顺序,这种所谓的动态绑定很容易出现问题,特别是系统较大可能会存在很多日志框架,就会出现混乱,不够灵活,这就导致了为啥JCL已经被慢慢淘汰掉。

slf4j采用的静态绑定,不是直接和日志框架进行绑定,而是中间多了一个环节:绑定类,它就像一个开关一样,关键是可以进行控制,比如想和log4j2进行绑定,就添加log4j-slf4j-impl.jar,开关就会打开进行绑定。slf4j不管是采用StaticLoggerBinder还是后面采用的SPI,始终有个绑定类控制绑定关系。

总结

Java日志组件选型的建议

统一日志API采用SLF4J,在模块中引入slf4j-api,需要绑定日志框架中引入logback-classic日志实现框架选型:如果最求高并发、高性能、日志量特别大的项目,可以采用Log4j2,否则都采用LogbackSpringBoot2.0开始,默认内置使用logback+slf4j方式,所以从趋势上来说,项目中优先建议采用这个组合方式

再一个就是对slf4jjcl两种日志框架绑定机制的分析,学习了接口和实现类松耦合关系最后又是如何在运行时进行绑定,或许可以为我们以后的系统设计提供些思路,从而构建出更加灵活的、可扩展的应用。

标签:

相关阅读

【编程开发】- 01 日志框架

快讯

Log4j是目前最为流行的Java日志框架之一,1999年发布首个版本,2012年发布最后一个版本,2015年正式宣布终止,官方也已不建议使用,并逐步被Logb

2023-03-28

三家“核电巨头”陆续拜访广东省

快讯

今年3月,国家电投、华能集团、中广核集团这三家核电巨头的“一把手”陆续拜访了广东省高层领导。3月22日,中国广核集团董事长杨长利在济南拜

2023-03-28

中国投资环境的影响因素有哪些?如何改善中

快讯

影响中国投资环境的因素有哪些呢?影响和决定中国投资环境的因素很多:(1)社会政治因素。国家稳定、国家安全的国家和地区,投资风险低,自然

2023-03-28

普惠金融定向降准是什么意思?普惠金融是做

快讯

普惠金融是做什么的?普惠金融是指能够为所有社会阶层和集体提供有益和全面服务的金融体系,旨在使老百姓能够享受更多的金融服务,更好地支

2023-03-28

如何网上汇款?网上汇款流程有哪些?

快讯

如何网上汇款,网上汇款有哪些方式方法?方法一、通过银行柜台办理汇款业务流程优点:方便安全缺点:拖延时间,不够及时1、首先,在柜台拿起

2023-03-28

【编程开发】- 01 日志框架

快讯

Log4j是目前最为流行的Java日志框架之一,1999年发布首个版本,2012年发布最后一个版本,2015年正式宣布终止,官方也已不建议使用,并逐步被Logb

2023-03-28

三家“核电巨头”陆续拜访广东省

快讯

今年3月,国家电投、华能集团、中广核集团这三家核电巨头的“一把手”陆续拜访了广东省高层领导。3月22日,中国广核集团董事长杨长利在济南拜

2023-03-28

中国投资环境的影响因素有哪些?如何改善中国投资环境呢?

快讯

影响中国投资环境的因素有哪些呢?影响和决定中国投资环境的因素很多:(1)社会政治因素。国家稳定、国家安全的国家和地区,投资风险低,自然

2023-03-28

普惠金融定向降准是什么意思?普惠金融是做什么的?

快讯

普惠金融是做什么的?普惠金融是指能够为所有社会阶层和集体提供有益和全面服务的金融体系,旨在使老百姓能够享受更多的金融服务,更好地支

2023-03-28

如何网上汇款?网上汇款流程有哪些?

快讯

如何网上汇款,网上汇款有哪些方式方法?方法一、通过银行柜台办理汇款业务流程优点:方便安全缺点:拖延时间,不够及时1、首先,在柜台拿起

2023-03-28

股票收购请求权是什么意思?股票收购请求权特征有哪些?

快讯

股票收购请求权是什么意思?所谓的股票收购请求权指的是想收购(某个企业)收购之前対上级部门可以发出的请示的权利。例如,持异议的股东股权

2023-03-28

ddx是什么意思?ddy是什么意思?ddz是什么意思?

快讯

ddx是什么意思?ddy是什么意思?ddz是什么意思?1 DDX是大单的走势大单的走势是基于大智慧LEVEL-2的单一分析函数,是一个中短线的技术指标。DD

2023-03-28

成都贷款担保公司怎么选?贷款为什么需要找担保公司?

快讯

成都贷款担保公司怎么选?主要根据以下几点来分析一下。1、调查公司的声誉和规模、经营时间等一般来说,大型担保公司或机构抗风险能力较强,

2023-03-28

高位放量滞涨是什么意思?高位放量滞涨在市场上有什么意义?

快讯

高位放量滞涨是什么意思?高位放量滞涨是指当股票价格运行到市场高点时,成交量明显扩大,但股票价格并不随着成交的扩大而上升,相反的话,

2023-03-28

程序化交易是什么?程序化交易的优点和缺点是什么?

快讯

程序化交易是一种在计算机和网络技术的支持下,可以即时完成你预设的组合交易指令的交易方式。你可以用你的交易思路,通过文华,提供的函数

2023-03-28

遇见旗袍是于万千人群中的惊鸿一瞥 沿途洒满了爱的芬芳

旗袍,中国和世界华人女性的传统服装,被誉为中国国粹和女性国服。虽然其定义和产生的时间至今还存有诸多争议,但它仍然是中国悠久服饰文化

北京市电影院有序恢复开放 周五预售部分场次已满座

7月21日,北京市政府发布《北京市电影局关于在疫情防控常态化条件下有序推进电影院恢复开放的通知》,宣布全市低风险地区影院,可于7月24日

近期持续强降雨影响 第46届武汉渡江节因长江水位过高取消

武汉7·16渡江节组委会14日发布公告,由于长江武汉关水位超警戒水位,按照规定取消2020年第46届武汉7·16渡江节。受近期持续强降雨影响,

“非遗”普及受众最看重“动手”参观大师工作室非常享受

过去一段时间,国家级非遗项目灰塑传承人邵成村,多次在陈家祠等工作现场,向身边那些带着好奇目光的人们讲解灰塑的种种技术细节:草根灰、

璧山冷酒夜市 丰富市民夜间文旅活动

7月13日,位于璧山区南门唐城夜市街区的璧山冷酒夜市开街。这是璧山区打造夜间经济消费载体、培育夜间经济活动品牌的举措之一。璧山市民一

年内两市超过500家上市公司完成回购 累计回购金额超332亿元

近期A股市场持续震荡,不少上市公司或其重要股东推出回购、增持计划,用真金白银力挺股价。记者根据同花顺数据统计,今年以来,两市超过500

持续发力补链强链加大研发抢占市场 渝企跑出“加速度”

玥湖路渝快电充换电站 一辆新能源汽车,离不开研发、动力、配套等多个环节。作为汽车制造重镇,重庆在这些环节的多个板块上,正在加速奔跑

重启上市公司资本运作 康佳集团去年半导体业务营业收入为3.22亿元

近日,康佳集团正式对外发布2021年年度业绩报告。2021年,康佳集团实现全年营收491 07亿元,归属于母公司的净利润为9 05亿元,同比增长89 5

伟禄集团连续6年增长 去年营收同比增长37.5%

深港通标的之一的深圳企业伟禄集团近日公布2021年业绩。财报数据显示,伟禄集团全年营业收入11 95亿港元,同比增长37 5%,连续6年稳步增长;

龙头企业去年净利倍增 整个行业营收规模有望创造历史新高位

近日,面板龙头TCL科技、京东方分别发布2021年度业绩快报,两家企业去年归属于上市公司股东的净利润分别增长129 3%、412 86%,实现超过百亿

深圳国企全力为市民 守好“菜篮子”“米袋子”保障量足价稳

疫情防控形势下,民生物资供应是否充足成为市民最为关注的问题之一。连日来,深农集团、深粮控股等企业,充分发挥国企担当,全力为深圳市民