Spring框架基础(spring框架详解)
ccwgpt 2024-10-16 08:11 39 浏览 0 评论
关于框架
框架(Framework)一个框架是一个可复用的设计构件,它规定了应用 的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供了上下文(Context)关系。
应用框架指的是实现了某应用领域通用完备功能(除去特殊应用的部分) 的底层服务。使用这种框架的编程人员可以在一个通用功能已经实现的基础上开始具体的系统开发。框架提供了所有应用期望的默认行为的类集合。 具体的应用通过重写子类(该子类属于框架的默认行为)或组装对象来支持应用专用的行为。
虽然使用框架对你的开发有很大的帮助,但是,与此同时,你也会受到框架的约束,例如,假设你的“毛胚房”(框架的比喻)是东西朝向的,你是没有办法通过 正常的手段把它变成一个南北朝向的房子的。 所以,在学习一款框架时,应该更多的关注框架的正确使用方式,从而实现你预期的目标。
关于Spring框架
Spring框架主要解决了创建对象、管理对象的问题。
在开发实践中,Spring框架的核心价值在于:开发者可以通过Spring框 架提供的机制,将创建对象、管理对象的任务交给Spring来完成,以至于 开发者不必再关心这些过程,当需要某个对象时,只需要通过Spring获取 对象即可。 – Spring框架也经常被称之为:Spring容器
Spring框架还很好的支持了AOP,此部分将在后续课程中再介绍。
创建对象并不是一个复杂的任务,假设项目中存在类:
public class UserMapper {
public void insert() {
// 向数据表中的“用户表”中插入数据
} }
//创建对象 new
UserMapper userMapper = new UserMapper();
//在开发实践中,类与类之间是存在依赖关系的,例如:
public class UserController {
public UserMapper userMapper;
public void reg() {
userMapper.insert();
以上userMapper属性如果不赋值,则程序将无法正确运行; – 在整个项目运行过程中,UserMapper对象只需要1个且始终存在即可; – 如果自行创建对象,当多个类都依赖UserMapper时,各自创建UserMapper对象, 违背了以上“只需要1个”的思想 }
}
以上userMapper属性如果不赋值,则程序将无法正确运行;
- – 在整个项目运行过程中,UserMapper对象只需要1个且始终存在即可;
- – 如果自行创建对象,当多个类都依赖UserMapper时,各自创建UserMapper对象, 违背了以上“只需要1个”的思想
在开发实践中,有许多类型的对象、配置值都需要常驻内存、需要有唯一 性,或都需要多处使用,自行维护这些对象或值是非常繁琐的,通过 Spring框架可以极大的简化这些操作。
在Maven工程中使用Spring
- 当某个项目需要使用Spring框架时,推荐使用Maven工程。
- 使用Spring框架所需的依赖项是 spring-context,依赖代码为:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.14</version> // 版本号按需修改
</dependency>
通过Spring管理对象
创建对象的方式
- 如果需要Spring管理对象,就必须先创建对象,然后Spring获取到对象 才可以进行管理
- 被Spring管理的对象,通常也称之为Spring Bean
- 创建对象的方式有2种:① – 通过@Bean方法 ②– 通过组件扫描
(1)通过@Bean方法创建对象
编码步骤:
- – 创建cn.tedu.spring.SpringBeanFactory类
- – 在类中添加方法,方法的返回值类型就是你希望Spring创建并管理的对象的类型, 并在此方法中自行编写返回有效对象的代码
- – 在此类上添加@Configuration注解 – 在此方法上添加@Bean注解
package cn.tedu.spring;
//@Bean创建方式 示例:
@Configuration
public class SpringBeanFactory {
@Bean
public Random random() {
return new Random();
}
}
测试运行的编码步骤:
- – 创建任意类,在类中添加main()方法,将通过此方法测试运行,以观察运行效果
- – 如果你已经掌握JUnit的用法,且添加了JUnit依赖,也可以使用JUnit测试
- – 创建AnnotationConfigApplicationContext类型的对象,并使用添加了 @Configuration注解的类作为构造方法参数
- – 这是ApplicationContext接口的实现,通常称之为Spring的应用程序上下文
- – 调用AnnotationConfigApplicationContext对象的getBean()方法,以获取@Bean 注解方法返回的对象
- – 自行测试获取的对象
- – 调用AnnotationConfigApplicationContext对象的close()方法,以关闭
//测试运行代码步骤
public class SpringRunner {
public static void main(String[] args) {
// 1. 加载Spring
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringBeanFactory.class);
// 2. 从Spring中获取对象
Random random = (Random) ac.getBean("random");
// 3. 测试使用对象,以便于观察是否获取到了有效的对象
System.out.println("random > " + random);
// 4. 关闭
ac.close();
}
}
【注意】
- – 在AnnotationConfigApplicationContext的构造方法中,应该将 SpringBeanFactory.class作为参数传入,否则就不会加载SpringBeanFactory类 中内容
- – 实际上,在以上案例中,SpringBeanFactory类上的@Configuration注解并不是必须的,但@Bean方法的使用规范是将其声明在@Configuration类中
- – 在getBean()时,传入的字符串参数"random"是SpringBeanFactory类中的@Bean方法的名称
- – 在SpringBeanFactory类中的方法必须添加@Bean注解,其作用是使得Spring框架自动调用此方法,并管理此方法返回的结果
- – 关于getBean()方法,此方法被重载了多次,典型的有:
- – Object getBean(String beanName) 通过此方法,传入的beanName必须是有效的,否则将导致 NoSuchBeanDefinitionException
- – T getBean(Class<T> beanClass); 使用此方法时,传入的类型在Spring中必须有且仅有1个对象,如果Spring容器中没 有匹配类型的对象,将导致NoSuchBeanDefinitionException,如果有2个或更多, 将导致NoUniqueBeanDefinitionException
- – T getBean(String beanName, Class<T> beanClass) 此方法仍是根据传入的beanName获取对象,并且根据传入的beanClass进行类型转换
- – 使用的@Bean注解可以传入String类型的参数,如果传入,则此注解对应的方法的 返回结果的beanName就是@Bean注解中传入的String参数值,后续调用getBean() 方法时,如果需要传入beanName,就应该传入在@Bean注解中配置的String参数值
package cn.tedu.spring;
@Configuration
public class SpringBeanFactory {
@Bean("random")
public Random xxx() {
return new Random();
}
}
(2)通过组件扫描创建对象
编码步骤:
- – 自行创建某个类,例如创建cn.tedu.spring.UserMapper类,并在类的声明之前添加@Component注解
- – 自行创建某个类,例如创建cn.tedu.spring.SpringConfig类,并在类的声明之前添加2个注解:
- – @Configuration
- – @ComponentScan,且在注解参数指定包名为cn.tedu.spring
package cn.tedu.spring;
@Component
public class UserMapper { }
//示例代码
package cn.tedu.spring;
@Configuration
@ComponentScan("cn.tedu.spring")
public class SpringConfig { }
测试运行的编码步骤:
- – 与前序编写测试运行代码的方式相同
- – 调用getBean()获取对象时,传入的beanName是:将UserMapper的类名首字母改为小 写,即userMapper
public class SpringRunner {
public static void main(String[] args) {
// 1. 加载Spring
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
// 2. 从Spring中获取对象
UserMapper userMapper = ac.getBean("userMapper", UserMapper.class);
// 3. 测试使用对象,以便于观察是否获取到了有效的对象
System.out.println("userMapper > " + userMapper);
// 4. 关闭
ac.close();
}
}
配置@Component注解参数以指定beanName
//获取对象时,需使用 userMapperBean 作为beanName, 而不是 userMapper 作为beanName
package cn.tedu.spring;
@Component("userMapperBean")
public class UserMapper { }
配置注解属性
在配置注解属性时,value是默认的属性,当注解只需要配置value这1个 属性的值时,可以缺省,例如以下2种语法是完全等效的:
//以下2种语法是完全等效的:
@ComponentScan("cn.tedu.spring")
@ComponentScan(value = "cn.tedu.spring")
在配置注解属性时,如果属性类型是数组类型的,却只需要配置1个值, 可以不使用大括号框住属性值,例如以下2种语法是完全等效的:
@ComponentScan("cn.tedu.spring")
@ComponentScan({"cn.tedu.spring"})
//如果数组类型的属性需要配置多个值,则必须使用大括号框住所有 值,各值之间使用逗号分隔
组件注解
除了@Component以外,在Spring框架中还可以使用@Repository、 @Service、@Controller表示某个类是组件类
package cn.tedu.spring;
@Component
public class UserMapper { }
//这4个注解选择其中1个使用即可,例如上下的这代码片段是等效的:
package cn.tedu.spring;
@Repository
public class UserMapper { }
@Repository、@Service、@Controller使用@Component作为元注解 (Meta Annotation),并且,这3个注解的value属性都等效于 @Component的value属性,通过源代码可以看出这些特点,以 @Repository为例:
在Spring框架的解释范围内,组件注解的用法及作用表现是完全相同的, 但字面语义不同,在开发实践中,应该根据类的定位进行选取:
- – @Repository:用于实现数据访问的类
- – @Service:用于处理业务逻辑的类
- – @Controller:用于控制器类
- – @Component:通用组件注解,即:不适合使用以上注解的组件类则添加此注解
- @Configuration也使用了@Component作为元注解所以,此注解也可 以视为“组件注解”,但是Spring框架对其处理方式更为特殊(使用了代理模式),所以仅当某个类的作用是编写各种配置代码时,才会使用 @Configuration。
总结:2种创建对象的方式,对比如下:
- – 通过@Bean方法:需要在配置类中添加@Bean方法,需要Spring管理的对象越多, 则需要添加的@Bean方法就越多,虽然每个方法的代码并不复杂,但是当方法的数 量到一定程度后也比较繁琐,不易于管理,这种做法的优点是可以完全自定义对象的 创建过程,在@Bean方法内部仍是传统的创建对象的语句
- – 通过组件扫描:只需要配置1次组件扫描,然后各组件类添加组件即可,且各组件类 添加组件注解后也可增强语义,所以,无论编码成本还是代码的可读性都更好,这种 做法的不足在于“只能适用于自定义的类”,毕竟你不可以在引用的库中的类上添加 组件注解
Spring Bean的作用域
在默认情况下,由Spring Bean的作用域是单例的
单例的表现为:实例唯一,即在任意时刻每个类的对象最多只有1个,并 且,当对象创建出来之后,将常驻内存,直至Spring将其销毁(通常是 ApplicationContext调用了销毁方法,或程序运行结束)
注意:这与设计模式中的单例模式无关,只是作用域的表现完全相同
可以通过@Scope注解修改作用域
- – 当通过@Bean方法创建对象时,在方法的声明之前添加@Scope注解
- – 当通过组件扫描创建对象时,在组件类的声明之前添加@Scope注解
//方法上申明
@Configuration
public class SpringBeanFactory {
@Scope
@Bean
public Random random() {
return new Random();
} }
//组件类上申明
@Scope
@Repository
public class UserMapper { }
@Scope注解的scopeName属性决定了作用域,此属性与value是互相等 效的,所以,通常配置为value属性即可
@Scope注解的scopeName属性的常见取值有:
- – singleton:单例的 – 事实上这是默认值,在scopeName属性的源码上明确的说明了:Defaults to an empty string "" which implies ConfigurableBeanFactory.SCOPE_SINGLETON,且以上常 量的值就是singleton
- – prototype:原型,是非单例的
- – 还有其它取值,都是不常用取值,暂不关心
当需要将Spring Bean的作用域改为“非单例的”
@Configuration
public class SpringBeanFactory {
@Scope("prototype")
@Bean
public Random random() { return new Random(); }
}
//以下非单例
@Scope("prototype")
@Repository
public class UserMapper { }
- 你可以反复通过getBean()获取对象,会发现各对象的hashCode()返回的 结果都不相同
- – 如果hashCode()没有被恶意重写,不同对象的hashCode()必然不同
- 由于不配置@Scope,与配置为@Scope("singleton")是等效的,所以, 仅当需要将Spring Bean的作用域改为“非单例的”,才会添加配置为 @Scope("prototype")
在默认情况下,单例的Spring Bean是预加载的,必要的话,也可以将其 配置为懒加载的
– 如果某个对象本身不是单例的,则不在此讨论范围之内
预加载的表现为:加载Spring环境时就会创建对象,即加载Spring配置 的环节会创建对象
懒加载的表现为:加载Spring环境时并不会创建对象,而是在第1次获取 对象的那一刻再创建对象
可以通过@Lazy注解来配置懒加载
- – 当通过@Bean方法创建对象时,在方法的声明之前添加@Lazy注解
- – 当通过组件扫描创建对象时,在组件类的声明之前添加@Lazy注解
@Configuration
public class SpringBeanFactory {
@Lazy
@Bean
public Random random() { return new Random(); }
}
//组件扫描
@Lazy
@Repository
public class UserMapper { }
@Lazy注解的value属性是boolean类型的,表示“是否懒加载”
@Lazy注解的参数是不需要关心的,因为:
– 单例的Spring Bean默认就是预加载的,不是懒加载的,所以,保持默认状态时,不使用@Lazy注解即可,并不需要配置为@Lazy(false)
– @Lazy注解的value属性默认为true,所以,当需要将单例的Spring Bean配置为懒加载时,只需要添加@Lazy注解即可,并不需要配置为@Lazy(true)
懒加载与预加载优点:
预加载的优点在于:事先创建好对象,无论何时需要获取对象,都可以直 接获取,缺点在于:相当于启动程序时就会创建对象,这样的对象越多, 启动过程就越慢,并且,如果某个对象创建出来以后,在接下来的很长一 段时间都不需要使用,而此对象却一直存在于内存中,则是一种浪费 。
懒加载的优点在于:仅当需要对象时才会创建对象,不会形成浪费,缺点 在于:如果当前系统已经负荷较重,需要的对象仍未加载,则会增加系统 负担
相比而言,在开发实践中,通常认为预加载是更合理的配置
小结(需要掌握的点)
1)Spring可以将创建出来的对象管理起来,对于开发者而言, 当需要某个类的对象时,只需要从Spring容器中获取即可
2)创建对象方式:
- – 通过@Bean方法:在配置类中自定义方法,返回需要Spring管理的对象,此方法必 须添加@Bean注解
- – 通过组件扫描:在配置类中使用@ComponentScan指定需要扫描的包,并确保需要 Spring管理对象的类都在此包或其子孙包下,且这些类必须添加@Component、 @Repository、@Service、@Controller中的其中某1个注解
- – 如果需要Spring管理的是自定义的类的对象,应该使用组件扫描的做法,如果需要 Spring管理的对象的类型不是自定义的,只能使用@Bean方法的做法
3)使用组件扫描时,在@ComponentScan中指定的包是扫描 的根包,其子孙包中的类都会被扫描,通常,指定的包不需要特别精准, 但也不宜过于粗糙,你应该事先规划出项目的根包并配置在组件扫描中, 且保证自定义的每个组件类都在此包或其子孙包中
4)在Spring框架的解释范围内,@Component、 @Repository、@Service、@Controller的作用是完全相同的,但语义 不同,应该根据类的定位进行选取
5)@Configuration是特殊的组件注解,Spring会通过代理模 式来处理,此注解应该仅用于配置类
6)使用@Bean方法时,beanName默认是方法名,也可以在 @Bean注解中配置参数来指定beanName
7)使用组件扫描时,beanName默认是将类名首字母改为小 写的名称(除非类名不符合首字母大写、第2字母小写的规律),也可以 在@Component或其它组件注解中配置参数来指定beanName
8)Spring Bean的作用域默认是预加载的单例的,可以通过 @Scope("prototype")配置为“非单例的”,在单例的前提下,可以通过 @Lazy配置为“懒加载的”,通常,保持为默认即可
9)关于配置注解参数:
- – 如果你需要配置的只是注解的value这1个属性,不需要显式的写出属性名称
- – 如果你需要配置注解中的多个属性,每个属性都必须显式写出属性名称,包括value 属性
- – 如果你需要配置的注解属性的值是数组类型,当只指定1个值时,可以不使用大括号 将值框住,当指定多个值时,多个值必须使用大括号框住,且各值之间使用逗号分隔
- – 你可以通过查看注解的源代码来了解注解可以配置哪些属性、属性的值类型、默认值
- – 在注解的源代码中,@AliasFor可理解为“等效于”
自动装配
自动装配机制
Spring的自动装配机制表现为:当某个量需要被赋值时,可以使用特定的 语法,使得Spring尝试从容器找到合适的值,并自动完成赋值
最典型的表现就是在类的属性上添加@Autowired注解,Spring就会尝试 从容器中找到合适的值为这个属性赋值
package cn.tedu.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired // 注意:此处使用了自动装配的注解
private UserMapper userMapper;
public void reg() {
System.out.println("UserController.reg() >> 控制器即将执行用户注册……");
userMapper.insert();
// 注意:此处调用了userMapper属性的方法
}
}
//代码解析:
//– 在main()方法中,由于加载了SpringConfig类,根据SpringConfig上配置的
@ComponentScan,将执行组件扫描
//– 由于UserMapper和UserController都在组件扫描的包范围内,
所以Spring框架会 自动调用它们的构造方法以创建对象,
并把对象保管在Spring容器中
//– 由于UserController中的userMapper属性添加了@Autowired注解,
所以Spring框 架会尝试为此属性注入值,且由于在Spring容器中存在UserMapper对象,
则可以成 功注入,使得userMapper属性是有值的
//– 最终userController调用reg()方法时,实现过程中还通过userMapper调用了 insert()方法,
整个执行过程中不会出错,在控制台可以看到对应的输出文本
除了对属性装配以外,Spring的自动装配机制还可以表现为:
- 如果某个方法是由Spring框架自动调用的(通常是构造方法,或@Bean方法),当这个方法被声明了参数时,Spring框架也会自动的尝试从容器找到匹配的 对象,用于调用此方法
- 对方法的参数自动装配时,如果方法有多个参数,各参数的先后顺序是不 重要的
@Autowired的装配机制
关于@Autowired的装配机制,首先,会根据需要装配的数据的类型在 Spring容器中统计匹配的Bean(对象)的数量 。当匹配的Bean数量为0个时,判断@Autowired注解的required属性值
- – true(默认):装配失败,启动项目时即抛出NoSuchBeanDefinitionException
- – false:放弃自动装配,不会报告异常,后续直接使用此属性时,会出现NPE
当匹配的Bean数量为1个时,将直接装配,且装配成功。当匹配的Bean数量为多个时:自动尝试按照名称实现装配(即:要求属 性名称与beanName相同)
- – 存在与属性名称匹配的Spring Bean:装配成功
- – 不存在与属性名称匹配的Spring Bean:装配失败,启动项目时即抛出 NoUniqueBeanDefinitionException
小结(需要掌握的知识点)
- 当某个属性需要被注入值,且你肯定此值存在于Spring容器 中,你可以在属性上添加@Autowired注解,则Spring框架会自动为此属 性注入值
- 如果某个方法是由Spring调用的,当方法体中需要某个值, 且你肯定此值存在于Spring容器中,你可以将其声明为方法的参数,则 Spring框架会自动从容器中找到此值并且于调用此方法,如果声明了多个 这样的参数,各参数的先后顺序是不重要的
- 自动装配的前提是Spring会自动创建此类的对象,否则, Spring不可能为属性赋值,也不可能调用类中的方法
- @Autowired的装配机制的表现是可以根据类型实现装配, 并且,当匹配类型的Bean有多个时,还可以根据名称进行匹配,从而实 现装配,你需要熟记具体装配机制
学习记录,如有侵权请联系删除。
相关推荐
- 用Steam启动Epic游戏会更快吗?(epic怎么用steam启动)
-
Epic商店很香,但也有不少抱怨,其中一条是启动游戏太慢。那么,如果让Steam启动Epic游戏,会不会速度更快?众所周知,Steam可以启动非Steam游戏,方法是在客户端左下方点击“添加游戏”,然...
- Docker看这一篇入门就够了(dockerl)
-
安装DockerLinux:$curl-fsSLhttps://get.docker.com-oget-docker.sh$sudoshget-docker.sh注意:如果安装了旧版...
- AYUI 炫丽PC开发UI框架2016年6月15日对外免费开发使用 [1]
-
2016年6月15日,我AY对外发布AYUI(WPF4.0开发)的UI框架,开发时候,你可以无任何影响的去开发PC电脑上的软件exe程序。AYUI兼容XP操作系统,在Win7/8/8.1/10上都顺利...
- 别再说C#/C++套壳方案多了!Tauri这“借壳生蛋”你可能没看懂!
-
浏览器套壳方案,C#和C++有更多,你说的没错,从数量和历史积淀来看,C#和C++确实有不少方式来套壳浏览器,让Web内容在桌面应用里跑起来。但咱们得把这套壳二字掰扯清楚,因为这里面学问可大了!不同的...
- OneCode 核心概念解析——Page(页面)
-
在接触到OneCode最先接触到的就是,Page页面,在低代码引擎中,页面(Page)设计的灵活性是平衡“快速开发”与“复杂需求适配”的关键。以下从架构设计、组件系统、配置能力等维度,解析确...
- React是最后的前端框架吗,为什么这么说的?
-
油管上有一位叫Theo的博主说,React是终极前端框架,为什么这么说呢?让我们来看看其逻辑:这个标题看起来像假的,对吧?React之后明明有无数新框架诞生,凭什么说它是最后一个?我说的“最后一个”不...
- 面试辅导(二):2025前端面试密码:用3个底层逻辑征服技术官
-
面试官放下简历,手指在桌上敲了三下:"你上次解决的技术难题,现在回头看有什么不足?"眼前的候选人瞬间僵住——这是上周真实发生在蚂蚁金服终面的场景。2025年的前端战场早已不是框架熟练...
- 前端新星崛起!Astro框架能否终结React的霸主地位?
-
引言:当"背着背包的全能选手"遇上"轻装上阵的短跑冠军"如果你是一名前端开发者,2024年的框架之争绝对让你眼花缭乱——一边是React这位"背着全家桶的全能选...
- 基于函数计算的 BFF 架构(基于函数计算的 bff 架构是什么)
-
什么是BFFBFF全称是BackendsForFrontends(服务于前端的后端),起源于2015年SamNewman一篇博客文章《Pattern:BackendsFor...
- 谷歌 Prompt Engineering 白皮书:2025年 AI 提示词工程的 10 个技巧
-
在AI技术飞速发展的当下,如何更高效地与大语言模型(LLM)沟通,以获取更准确、更有价值的输出,成为了一个备受关注的问题。谷歌最新发布的《PromptEngineering》白皮书,为这一问题提供了...
- 光的艺术:灯具创意设计(灯光艺术作品展示)
-
本文转自|艺术与设计微信号|artdesign_org_cn“光”是文明的起源,是思维的开端,同样也是人类睁眼的开始。每个人在出生一刻,便接受了光的照耀和洗礼。远古时候,人们将光奉为神明,用火来...
- MoE模型已成新风口,AI基础设施竞速升级
-
机器之心报道编辑:Panda因为基准测试成绩与实际表现相差较大,近期开源的Llama4系列模型正陷入争议的漩涡之中,但有一点却毫无疑问:MoE(混合专家)定然是未来AI大模型的主流范式之一。...
- Meta Spatial SDK重大改进:重塑Horizon OS应用开发格局
-
由文心大模型生成的文章摘要Meta持续深耕SpatialSDK技术生态,提供开自去年9月正式推出以来,Meta持续深耕其SpatialSDK技术生态,通过一系列重大迭代与功能增强,不断革新H...
- "上云"到底是个啥?用"租房"给你讲明白IaaS/PaaS/SaaS的区别
-
半夜三点被机房报警电话惊醒,顶着黑眼圈排查服务器故障——这是十年前互联网公司运维的日常。而现在,程序员小王正敷着面膜刷剧,因为公司的系统全"搬"到了云上。"部署到云上"...
- php宝塔搭建部署thinkphp机械设备响应式企业网站php源码
-
大家好啊,欢迎来到web测评。本期给大家带来一套php开发的机械设备响应式企业网站php源码,上次是谁要的系统项目啊,帮你找到了,还说不会搭建,让我帮忙录制一期教程,趁着今天有空,简单的录制测试了一下...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 用Steam启动Epic游戏会更快吗?(epic怎么用steam启动)
- Docker看这一篇入门就够了(dockerl)
- AYUI 炫丽PC开发UI框架2016年6月15日对外免费开发使用 [1]
- 别再说C#/C++套壳方案多了!Tauri这“借壳生蛋”你可能没看懂!
- OneCode 核心概念解析——Page(页面)
- React是最后的前端框架吗,为什么这么说的?
- 面试辅导(二):2025前端面试密码:用3个底层逻辑征服技术官
- 前端新星崛起!Astro框架能否终结React的霸主地位?
- 基于函数计算的 BFF 架构(基于函数计算的 bff 架构是什么)
- 谷歌 Prompt Engineering 白皮书:2025年 AI 提示词工程的 10 个技巧
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- ui自动化框架 (47)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)