最新要闻
- 今日看点:【创新突破 产业突围】周振宇带队前往陕西西安开展招商考察活动
- 全球热消息:小米13 Ultra官图公布:传承徕卡M系列相机设计 支持IP68
- 世界新消息丨埃安高管:特斯拉不是不能战胜 Hyper GT全面超越Model 3
- 简讯:2TB 1049元 1TB不到600:三星SSD/内存降价不买要涨价 国产存储顶上
- 售价17万的特斯拉要来了:谁开心、谁恐慌?
- 每日热点:ChatGPT之父辟谣:并未秘密训练GPT-5 短期内也不会
- ST华英说明申请撤销其他风险警示相关情况
- 当前热文:明晚发布!小米13 Ultra外观正式揭晓:更像相机了
- 全球热头条丨毁经典!《海贼王》真人剧集口碑扑街:日漫原著粉在线声讨
- 全球讯息:余承东预言:2025年是汽车行业分水岭、像2013年的手机行业
- 苹果将于6月推出多款新品!苹果表将迎史上最大的软件更新
- 我国自研高性能兆瓦级PEM电解水制氢装备发布:国产化率超90%
- 环球即时看!维生素ABCDE的作用及功能主治(维生素abcde的作用及功能)
- 今日报丨《百度智能驾驶开放白皮书》发布 面向车企开放四大能力
- 今头条!特斯拉中国工厂待遇如何?普通工人月薪1万块 父母看病都能报销
- 女子借朋友摩托车无证驾驶 在隧道“狂飙”拍抖音 朋友也惨了
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
【全球速看料】Spring AOP官方文档学习笔记(二)之基于注解的Spring AOP
1.@Aspect注解
(1) @Aspect注解用于声明一个切面类,我们可在该类中来自定义切面,早在Spring之前,AspectJ框架中就已经存在了这么一个注解,而Spring为了提供统一的注解风格,因此采用了和AspectJ框架相同的注解方式,这便是@Aspect注解的由来,换句话说,在Spring想做AOP框架之前,AspectJ AOP框架就已经很火了,而直接把AspectJ搬过来又不现实,因此,Spring想了一个折中的方案,即只使用AspectJ框架的声明,写法和定义方式(比如@Aspect注解),而底层由Spring自己实现,这样,就避免了我们程序员从AspectJ AOP切换到Spring AOP后,还要再去学一套新的写法了,也正因为如此,如果想要使用Spring AOP,就必须依赖aspectjweaver.jar包(不然谁来提供写法和定义方式),我们可以通过maven进行导入,如下
org.aspectj aspectjrt 1.9.5 org.springframework spring-aspects ${spring.framework.version}
(2) 同时还需使用@EnableAspectJAutoProxy注解来开启Spring对于AspectJ注解的支持,如下
(资料图片)
@Configuration@EnableAspectJAutoProxypublic class Config {}
如果是基于xml的配置,可通过如下标签进行开启
2.自定义一个切面类
(1) 在基于注解的配置下,除了使用@Aspect注解外,还需要声明该切面是一个bean,否则,spring在扫描过程中是会忽略掉这个类的,如下
@Aspect@Componentpublic class Logger {}
(2) 对上面的例子,基于xml配置的写法如下
@Aspectpublic class Logger {}
(3) 由@Aspect注解标注的类,称之为切面类,与普通的类一样,都有成员方法与成员变量,不同的是,切面类还可以包含连接点,通知,引介等与AOP有关的东西
(4) 切面不能再被增强,如果想拿一个切面来增强另一个切面,是不可能的,Spring会将切面类从自动代理(auto-proxying)中排除
3.自定义一个切入点
(1) Spring AOP中的切入点目前只可能是bean中的方法,而对于一个普通类中的方法,是不可能成为切入点的,在Spring中,声明一个切入点主要包括两个部分:一个切入点签名以及一个切入点表达式,如下
//如下定义了一个叫做anyExampleAMethod的切入点,这个切入点会匹配cn.example.spring.boke包下的ExampleA类中的任何方法//其中,(1)就代表的是切入点表达式,(2)就代表的是切入点签名,注意,这个签名的返回值必须是void@Pointcut("execution(* cn.example.spring.boke.ExampleA.*(..))") //(1)public void anyExampleAMethod() {} //(2)
(2) Spring AOP的切入点表达式中,支持如下等切入点标识符
execution:最为常用,用于匹配某个包,某个类中的方法
within:进行类型匹配,用于匹配某个包下所有类的所有方法或某个指定类中的所有方法,如下
//指定了within的类型,这个切入点会匹配cn.example.spring.boke包下ExampleA类中的任何方法@Pointcut("within(cn.example.spring.boke.ExampleA)")public void withinDesignator(){}
- this:进行类型匹配,用于匹配生成的代理对象的类型是否为指定类型,如下
//此前我们提到过,Spring AOP中的底层实现分为jdk动态代理和cglib动态代理,jdk动态代理基于接口,要求目标对象必须实现某个接口,而cglib动态代理基于继承,因此不同的实现方式下,导致Spring生成的代理对象的类型可能不同,这就是this标识符的基础//首先定义一个接口public interface Parent { void register(); void sendEmail();}//让我们的ExampleA类,实现这个接口@Componentpublic class ExampleA implements Parent{ public void register() { } public void sendEmail() { }}//设置@EnableAspectJAutoProxy注解中的proxyTargetClass属性值为false,表示使用jdk动态代理,为true,表示使用cglib动态代理,默认值为false,不过我们这里显式的声明出来@Configuration@EnableAspectJAutoProxy(proxyTargetClass = false)@ComponentScan(basePackages = "cn.example.spring.boke")public class Config {}//切面类,在其中声明一个this标识符,并指定类型为ExampleA@Aspect@Componentpublic class Logger { /** * this标识符,进行类型匹配,用于匹配代理对象的类型是否为指定类型 */ @Pointcut(value = "this(cn.example.spring.boke.ExampleA)") public void thisDesignator(){} @Around(value = "thisDesignator()") public void around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println(new Date() + " 开始执行..."); joinPoint.proceed(); System.out.println(new Date() + " 结束执行..."); }}//执行如下打印方法,可见通知未被执行,原因就是因为我们使用了jdk动态代理,Spring为我们生成的代理对象继承自jdk中的Proxy类并实现了Parent接口,它不属于ExampleA类型,自然而然切入点匹配失败,我们的通知未被执行AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);ctx.getBean(Parent.class).register();ctx.getBean(Parent.class).sendEmail();//打印一下系统中代理对象的类型是否为ExampleA,结果为falseSystem.out.println(ctx.getBean(Parent.class) instanceof ExampleA);//为了能进行匹配,我们可以将@EnableAspectJAutoProxy中的proxyTargetClass属性设置为true,使用cglib动态代理,这时再执行上面的打印方法,通知就会被执行了,原因就是因为使用了cglib动态代理后,Spring为我们生成的代理对象是继承自ExampleA,当然属于ExampleA类型,因此通知会被执行@EnableAspectJAutoProxy(proxyTargetClass = true)
target:进行类型匹配,用于匹配目标对象的类型是否为指定类型,跟上面的this类似
args:进行方法参数匹配,用于匹配方法的参数类型是否为指定类型,如下
//ExampleA中的register方法的参数为String@Componentpublic class ExampleA{ public void register(String name) { } public void sendEmail() { }}@Aspect@Componentpublic class Logger { /** * 指定了args参数的类型为String,因此只会与ExampleA中的register方法匹配 */ @Pointcut(value = "args(java.lang.String)") public void argsDesignator() {} @Around(value = "argsDesignator()") public void around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println(new Date() + " 开始执行..."); joinPoint.proceed(); System.out.println(new Date() + " 结束执行..."); }}
@target:用于匹配目标对象的类上有没有标注指定注解
@args:用于匹配方法的参数的所属类上有没有标注指定注解
@within:用于匹配某个类上有没有标注指定注解
@annotation:最常用,用于匹配某个方法上有没有标注指定注解
(3) Spring的AOP是基于代理实现的,因此,在目标对象中进行内部调用是不会被拦截的(即this指针会导致AOP失效问题),此外,对于jdk动态代理,只能拦截public方法,而对于cglib动态代理,会拦截public和protected方法(package-visible 方法在配置后也能被拦截)
(4) Spring AOP还提供了一个PCD bean,用于按照bean的名称进行切入,它是Spring AOP独有的,如下
//匹配所有beanName以A结尾的bean@Pointcut("bean(*A)")public void pcd() {}
4.组合切入点表达式
(1) 可以通过 &&,|| 和 !来组合切入点表达式,如下
//切入所有public方法@Pointcut("execution(public * *(..))")public void allPublicMethod() {}//切入boke包下所有类中的所有方法@Pointcut("within(cn.example.spring.boke.*)")public void methodInBokePackage() {}//使用 && 操作符,将上面两个切入点表达式组合起来,即切入boke包下所有类中的所有public方法@Pointcut("allPublicMethod() && methodInBokePackage()")public void allPublicMethodInBokePackage() {}
5.常见切入点表达式例子
(1)在实际工作中,我们的切入点表达式的通常形式为:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?),其中ret-type-pattern表示一个方法的返回类型, 用 * 号可以代表任何类型; name-pattern表示方法名称,用 * 可以进行全部或部分名称匹配; param-pattern表示方法参数,其中用()代表无参方法,用(..)代表任何数量的参数(0个或多个),用()代表1个参数,(, String)代表有两个参数,第一个参数可以是任何类型,而第二个参数只能是String类型; 除此之外,其他带有 ? 的都是选填项,可不填写
(2)常见例子
//匹配任意public方法 execution(public * *(..))//匹配任意名称以set开头的方法execution(* set*(..))//匹配com.xyz.service包下,AccountService类下的任意方法execution(* com.xyz.service.AccountService.*(..))//匹配com.xyz.service包下,任意类下的任意方法execution(* com.xyz.service.*.*(..))//匹配com.xyz.service包及其子包下,任意类下的任意方法execution(* com.xyz.service..*.*(..))//匹配com.xyz.service包下,任意类下的任意方法within(com.xyz.service.*)//匹配com.xyz.service包及其子包下,任意类下的任意方法within(com.xyz.service..*)//匹配代理对象的类型为AccountService的类下的任意方法this(com.xyz.service.AccountService)//匹配目标对象的类型为AccountService的类下的任意方法target(com.xyz.service.AccountService)//匹配方法参数只有一个且参数类型为Serializable的方法,注意它与execution(* *(java.io.Serializable))的一点区别:execution这个例子只能匹配参数类型为Serializable的方法,如果说某个方法的参数类型是Serializable的子类,是不会匹配的,而下面args这个例子可以匹配参数类型为Serializable或其子类的方法args(java.io.Serializable)//匹配标注了@Transactional注解的目标对象中的任意方法@target(org.springframework.transaction.annotation.Transactional)//匹配标注了@Transactional注解的类中的任意方法@within(org.springframework.transaction.annotation.Transactional)//匹配标注了@Transactional注解的任意方法@annotation(org.springframework.transaction.annotation.Transactional)//匹配方法的参数有且只有一个且该参数的所属类上标注了@Classified注解的任意方法@args(com.xyz.security.Classified)//匹配beanName为tradeService的bean中的任意方法bean(tradeService)//匹配所有以Service作为beanName结尾的bean中的任意方法bean(*Service)
6.编写良好的pointcuts
(1)Spring将切入点标识符分为3大类,分别为:
- Kinded:类型标识符,如execution, get, set, call等,它们都是根据类型进行选择,比如execution选择的都是可执行方法这一类型,其中除了execution,其他的都是AspectJ框架提供的
- Scoping:范围标识符,如within;
- Contextual:上下文标识符,如this, target和@annotation,它们都是根据方法所处的环境(比如在哪个类中)进行选择Spring建议一个良好的切入点表达式应该至少包括前两种类型(kinded和scoping,在这两种标识符中scoping又特别重要,因为它的匹配速度非常快,可以快速的排除掉那些不应该被处理的方法),此外在有根据上下文环境的需求时,可以包括contextual标识符
7.声明一个通知
(1)在前面已经提及过通知,它是增强的逻辑,与切入点相关联,会在切入点执行前或执行后执行,在Spring中总共分为5大类,如下
- Before Advice:使用@Before注解可定义前置通知,它会在切入点执行之前执行
@Aspect@Componentpublic class Logger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void before() { //... }}
- After Returning Advice:使用@AfterReturning注解可定义返回通知,它会在切入点"正常"执行之后执行
//一个普通的bean ExampleA@Componentpublic class ExampleA{ public String doSomething() { return "finish"; }}//有时候,我们可能需要访问切入点执行后的返回值,那么我们可以使用@AfterReturning注解中的returning属性来指定返回值的名称,然后再给这个切面方法添加一个形参,这个形参类型即为切入点执行后的返回值类型(或其父类型,但不能完全不一致,否则切面会切入失败),形参名要与刚刚设置过的returning属性值一致,如下例@Aspect@Componentpublic class Logger { @AfterReturning(value = "execution(* cn.example.spring.boke.ExampleA.*(..))", returning = "returnVal") public void afterReturning(Object returnVal) { System.out.println(new Date() + " 开始执行..."); System.out.println(returnVal); System.out.println(new Date() + " 结束执行..."); }}
- After Throwing Advice:使用@AfterThrowing注解可定义异常通知,它会在切入点触发异常之后执行
//同样,我们有时候也期望访问切入点执行过程中抛出的异常,与返回通知一致,例子如下@Aspect@Componentpublic class Logger { @AfterThrowing(value = "execution(* cn.example.spring.boke.ExampleA.*(..))", throwing = "throwable") public void afterReturning(Throwable throwable) { System.out.println(new Date() + " 开始执行..."); System.out.println(throwable); System.out.println(new Date() + " 结束执行..."); }}
- After (Finally) Advice:使用@After注解可定义后置通知,它会在切入点无论以何种方式执行(正常或异常)后执行,常用于释放资源等目的,类似于try-catch语句中的finally块,它与@AfterReturning的区别是,@AfterReturning只适用于切入点正常返回
@Aspect@Componentpublic class Logger { @After(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void afterReturning() { //... }}
- Around advice:使用@After注解可定义环绕通知,它既可以在切入点之前执行通知,又可以在切入点之后执行,甚至可以不用执行切入点,是最为灵活强大的通知
@Aspect@Componentpublic class Logger { //环绕通知方法可不声明形参,但如果要声明形参,第一个形参的类型必须是ProceedingJoinPoint类型,对ProceedingJoinPoint调用proceed方法后会导致切入点真正的执行,此外,proceed方法还有一个重载方法,我们可以对它传递一个Object[],那么当切入点执行时会以这个数组中的值作为方法参数值来执行 //我们可以调用一次,多次或根本不调用proceed方法 @Around(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void afterReturning(ProceedingJoinPoint joinPoint) { Object returnVal = null; try { //... returnVal = joinPoint.proceed(); //... } catch (Throwable e) { //... e.printStackTrace(); } return returnVal; }}
8.切入点信息获取
(1)有时候,我们期望获取到切入点相关信息,比如它的签名,形参等信息,Spring为我们提供了JoinPoint类型,用于获取相关信息,在前面的环绕通知的例子中,我们就已经使用了JoinPoint的子类型ProceedingJoinPoint,它添加了proceed方法,来显式的调用执行切入点
@Aspect@Componentpublic class Logger { //除了下面的例子外,使用JoinPoint,还可以获取到切入点的其他一些信息可参考api @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void before(JoinPoint joinPoint) { System.out.println("被拦截的类:" + joinPoint.getTarget().getClass().getName()); System.out.println("被拦截的方法:" + ((MethodSignature) joinPoint.getSignature()).getMethod().getName()); System.out.println("被拦截的方法参数:" + Arrays.toString(joinPoint.getArgs())); }}
9.通知执行顺序
(1)不同切面类中的通知,在默认情况下,按照所在切面类名字典序的排序越高,其优先级也就越高,如下
@Configuration@EnableAspectJAutoProxy@ComponentScan(basePackages = "cn.example.spring.boke")public class Config { }@Componentpublic class ExampleA{ public void doSomething() { System.out.println("doSomething..."); }}//声明两个切面类TimerLogger和OperationLogger@Aspect@Componentpublic class TimerLogger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void a() { System.out.println("timer..."); }}@Aspect@Componentpublic class OperationLogger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void a() { System.out.println("operation..."); }}//启动容器,观察打印结果AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);ctx.getBean(ExampleA.class).doSomething();//打印结果如下,OperationLogger中的前置通知先执行,TimerLogger中的前置通知后执行,就是因为O的字典序列大于T,因此OperationLogger中的通知的优先级高于TimerLogger中的,而对于前置通知而言,优先级越高的越先执行,对于后置通知,优先级越高的越后执行operation...timer...doSomething...//我们可以将TimerLogger改为ATimerLogger,这样的话它里面的前置通知就会先执行了@Aspect@Componentpublic class ATimerLogger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void a() { System.out.println("timer..."); }}
(2)我们可以对切面类实现Ordered接口或添加@Order注解来显示的指定优先级,其中指定的值越小,优先级越高
//此时TimerLogger的优先级高于OperationLogger@Aspect@Component@Order(1)public class TimerLogger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void a() { System.out.println("timer..."); }}@Aspect@Component@Order(2)public class OperationLogger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void a() { System.out.println("operation..."); }}
(3)对于同个切面类中的相同类型的通知,其优先级只与通知方法名字典序的排序有关,排序越高,优先级越高,如下
//Logger切面类中定义了两个前置通知为aPrint和bPrint@Aspect@Componentpublic class Logger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void aPrint() { System.out.println("a"); } @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") public void bPrint() { System.out.println("b"); }}//启动容器,可见aPrint先于bPrint,这就是因为a的字典序高于babdoSomething...//将aPrint改为caPrint,这时bPrint会先执行,因为此时它的字典序高@Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))")publicvoid caPrint() { System.out.println("a");}//此外使用@Order注解,无法改变优先级,因为此时显式指定优先级的策略已经失效了,如下面这个例子还是按照默认的优先级进行执行@Aspect@Componentpublic class Logger { @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") @Order(Ordered.LOWEST_PRECEDENCE) public void aPrint() { System.out.println("a"); } @Before(value = "execution(* cn.example.spring.boke.ExampleA.*(..))") @Order(Ordered.HIGHEST_PRECEDENCE) public void bPrint() { System.out.println("b"); }}
10.Introductions(引介)
(1)引介能够使指定的对象实现某些接口,并提供对这些接口的实现,以达到向对象中动态添加它所没有方法的目的,例子如下
//我们希望向ExampleA类中增加某些新的方法@Componentpublic class ExampleA{ }//声明一个接口,这个接口里的方法即为我们希望增加的新的方法public interface Extention { void doSomething();}//新方法的具体实现public class ExtentionImpl implements Extention{ @Override public void doSomething() { System.out.println("doSomething..."); }}//定义一个切面@Component@Aspectpublic class MyAspect { //使用@DeclarePrents注解,声明被拦截的类有一个新的父类型,其中value指定拦截哪些类,在下面这个例子中指定拦截cn.example.spring.boke包下的所有类,它们的父类型均为Extention,具体的实现为ExtentionImpl @DeclareParents(value = "cn.example.spring.boke.*", defaultImpl = ExtentionImpl.class) public Extention extention;}//开启AOP@Configuration@EnableAspectJAutoProxy@ComponentScan(basePackages = "cn.example.spring.boke")public class Config { }//启动容器,从容器中获取到exampleA并将其强制转换为Extention,这样我们就能使用向ExampleA中新添加的方法了AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);Extention exampleA = (Extention)ctx.getBean("exampleA");exampleA.doSomething();
关键词:
-
每日热文:MySQL 处理大数据表的 3 种方案,写的太好了,建议收藏!!
作者:马佩链接:https: juejin cn post 7146016771936354312场景当我们业务数据库表中的数据越来...
来源: -
【全球速看料】Spring AOP官方文档学习笔记(二)之基于注解的Spring AOP
1 @Aspect注解(1)@Aspect注解用于声明一个切面类,我们可在该类中来自定义切面,早在Spring之前,Aspec...
来源: 每日热文:MySQL 处理大数据表的 3 种方案,写的太好了,建议收藏!!
【全球速看料】Spring AOP官方文档学习笔记(二)之基于注解的Spring AOP
全球快资讯:exec 函数族 - 进程替换
今日看点:【创新突破 产业突围】周振宇带队前往陕西西安开展招商考察活动
全球热消息:小米13 Ultra官图公布:传承徕卡M系列相机设计 支持IP68
世界新消息丨埃安高管:特斯拉不是不能战胜 Hyper GT全面超越Model 3
简讯:2TB 1049元 1TB不到600:三星SSD/内存降价不买要涨价 国产存储顶上
售价17万的特斯拉要来了:谁开心、谁恐慌?
每日热点:ChatGPT之父辟谣:并未秘密训练GPT-5 短期内也不会
ST华英说明申请撤销其他风险警示相关情况
当前热文:明晚发布!小米13 Ultra外观正式揭晓:更像相机了
全球热头条丨毁经典!《海贼王》真人剧集口碑扑街:日漫原著粉在线声讨
全球讯息:余承东预言:2025年是汽车行业分水岭、像2013年的手机行业
苹果将于6月推出多款新品!苹果表将迎史上最大的软件更新
我国自研高性能兆瓦级PEM电解水制氢装备发布:国产化率超90%
环球即时看!维生素ABCDE的作用及功能主治(维生素abcde的作用及功能)
环球视讯![Flink] Flink作业报错:Caused by: The connector is trying to read binlog startin
每日热闻!央行圆桌汇:4月17日
今日报丨《百度智能驾驶开放白皮书》发布 面向车企开放四大能力
今头条!特斯拉中国工厂待遇如何?普通工人月薪1万块 父母看病都能报销
女子借朋友摩托车无证驾驶 在隧道“狂飙”拍抖音 朋友也惨了
世界快讯:真人版《小美人鱼》国内将上映!黑小美人鱼喊话自己可爱:我爱的人而战
全球百事通!全系800V高压、一体化铝压铸车身!小鹏SEPA 2.0扶摇架构发布
比原版多50分钟!真人版《小美人鱼》片长超2小时
热议:SoapUI使用教程-九五小庞
实时焦点:债市观察:做多情绪占优 收益率曲线平坦化下移
【读财报】制造主题基金2022年业绩透视:广发基金领亏 摩根基金净值跌幅最大
苹果设备不断要求输入Apple ID密码!客服回应:可尝试修改密码
环球今日讯!猿辅导被举报单日加班超6小时:上厕所需报备 时薪仅17元
当前快报:2022年全国共登记计算机软件著作权183.5万件:比十年前高12倍
全球快报:国内成品油零售价迎今年最大涨幅 加满多花70元:沙特俄罗斯减产 国际油价大涨
环球新资讯:卢谈G1:我们没有太多容错空间&不是试探性比赛 必须全力以赴
环球观点:学系统集成项目管理工程师(中项)系列08a_合同管理(上)
杭州萧山国际机场T3航站楼出现冒烟现象:无人受伤
天天视讯!今晚开始!国内成品油零售价迎今年最大涨幅:加满一箱多花20元
【全球报资讯】考研数据结构模板:顺序表、链表、栈、队列
世界热资讯!王一博、梁朝伟主演电影《无名》结束公映:85天票房9.31亿
热讯:RTX 4060 Ti、RTX 4060严重缩水:除了显存 还有一点没法看
天天视点!人类真是动物界最优秀的长跑运动员?别闹了
环球快报:一款车发布两年还没影!长城怎么这么难产?
当前聚焦:机械硬盘卖不动了 销量暴跌35%!三大品牌抱团哭惨
三代同堂!46岁皇马传奇古蒂升级当爷爷,22岁网红大女儿产下一子
天天关注:Node.js的安装以及配置npm全局模块路径和缓存路径
使用Sentieon加速甲基化(WGBS)分析
世界短讯!【明日方舟】4周年活动更新预测(第二版)
当前头条:4年不卡的骁龙8+旗舰来了!一加Ace 2原神限定版明天发:抢到赚到
全球视点!iOS 17控制中心将有大变化:有一批老设备不支持 将被淘汰
AMD、NVIDIA新一代显卡全部破发!次旗舰双双最惨
环球热议:扎实打牢数据结构算法根基,从此不怕算法面试系列之005 week01 02-05 使用自定义类测试我们前面实现的支持泛型的线性查找法
如何获取软件包的下载地址 wget curl
基于GPT3的代码编辑器Cursor试用-你的智能代码编辑助手
每日快播:React onBlur回调中使用document.activeElement返回body解决方案
世界观察:民营天龙二号液体火箭首飞成功:还隐藏了一个中国第一
天天看热讯:不知道这几点!你买电动牙刷就是花冤枉钱
世界热资讯!热泵干衣机被严重低估了!浑身都是宝
环球快播:致聂红的一封信
环球快报:2023上海车展丨这些即将首发的热门新车你一定不要错过!
云南泼水节白天是热闹夜晚是浪漫:市民游客共狂欢
员工回应公司发布高薪招聘老板公告:不是开玩笑
热推荐:java -- File类和递归
贾跃亭憋了九年的车终于量产?结果 又一张大饼!
环球快报:四边等宽的鸿蒙手机来了!华为nova 11明天发
潍坊风筝节放飞打工人的心声:引发网友热议
Intel鸡血驱动暴涨63%!Arc A750性价比秒杀RTX 3060 72%!
当前最新:天舟六号飞船、长征七号火箭抵达文昌!五次发射 100%成功
山东泰山队vs上海申花首发出炉:四外援先发,韩镕泽镇守球门
每日热讯!“泼水节被撕扯雨衣”女生发声:很崩溃
世界快报:众人狂欢!泼水节连狗路过都得淋两桶水再走
贝贝健电蚊香液到手14.9元:驱赶蚊虫神器 夏天必备
全球信息:超级SSD 21合一组成168TB!价格直奔20万元
全球视点!扎实打牢数据结构算法根基,从此不怕算法面试系列之001 week01 02-01 什么是算法?
焦点快报!女子花2万为猫移植鱼皮被网暴 本人:救治一半不可能放弃
全球热头条丨女子澄清妈妈做月嫂存款482万为虚构:觉得好玩就发了 现在很后悔
环球热文:养男三不碰,养女三讲究,教出来的孩子才能立足社会!
世界信息:Air724UG开发板串口教程
首发宁德时代麒麟电池 极氪009 ME版正式交付:根治续航焦虑
环球百事通!超智驾轿跑SUV!小鹏G6将亮相上海车展
学系统集成项目管理工程师(中项)系列06b_信息系统安全管理(下)
【打怪升级】【微服务】聊聊微服务拆分设计
微头条丨《世界尽头的咖啡馆》-热衷于有意义的事,追求真我。
31-触发器01
2023年4月自考《人力资源管理(一)》真题答案汇总
卡普空更新出尔反尔:突然移除《生化危机2/3》Steam版光追
世界速看:奥利奥礼包到手39元:夹心饼干、巧脆卷全都有
环球看点!Vulnhub Fall Walkthrough
环球消息!苹果在线服务又出Bug:用户被迫反复输入Apple ID
每日视点!余承东罕见认错:还连甩五项重磅技术更新
《灌篮高手》赤木刚宪预告 大猩猩怒吼霸气登场
每日看点!Visual Studio Code开发常用的工具栏选项,查看源码技巧以及【vscode常用的快捷键】
环球快资讯丨也门和平进程迎来重要机遇
环球时讯:《流浪地球2》网播热度不减:上线后全网热度登顶
今日热文:深入理解 JVM ------ 调优案例分析与实战
观热点:1年内5名机车网红车祸身亡:靠摩托车来吸睛涨粉 已成“流量密码”
世界热点评!当心寄生虫!女生15元买15个螺肉疑为福寿螺 央视科普如何区分
FreeSWITCH添加iLBC编码及转码
世界最资讯丨负数有奇数和偶数吗_奇数和偶数是什么意思
华为鸿蒙HarmonyOS 4.0来了!余承东确定秋天发布
世界热点评!熊猫“蔓越煤”胡萝卜卡喉 饲养员海姆立克法施救:不愧是“生命的拥抱”
最新消息:《3D编程模式》写书-第3次记录
全球焦点!推荐给你让人震惊的网站集合