容器(可以用来管理所有的组件(类))

核心关注:IOC和AOP

1.IOC

Inversion(反转) Of Control:控制反转
控制:资源的获取方式
1.主动式(要什么资源自己创建)
Person{
Book book=new Book();
Dog dog=new Dog();
//复杂对象的创建时比较庞大的工程
}
2.被动式:资源的获取不是自己创建,而是交给一个容器创建和设置
Person{
Book book;
public void test(){
book.read();
}
}
容器:管理所有的组件(有功能的类),主动的new资源改为被动的接受资源

1.1 DI(Dependency Injection)依赖注入

容器能知道哪个组件(类)运行的时候,需要另外一个组件(类);
容器通过反射的形式,将容器中准备好的Book对象注入(利用反射给属性赋值)到Person中
IOC只是思想,而DI是具体的实现
代码实现:
1.实体类
public class Person {
private String name;
private Integer age;
private String gender;
private String email;
public Person() {
System.out.println("person的构造器!");
}
public void setName(String name) {
System.out.println("设置pserson的name");
this.name = name;
}
public void setAge(Integer age) {
System.out.println("设置person的age");
this.age = age;
}
public void setGender(String gender) {
System.out.println("设置person的gender");
this.gender = gender;
}
public void setEmail(String email) {
System.out.println("设置person的email");
this.email = email;
}
....
...get()
}
2.spring的配置文件ioc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--注册person对象,spring会自动创建这个person对象-->
<bean class="com.Person" id="person01">
<property name="age" value="18"></property>------------->name是bean中的属性,通过set方法反射注入
<property name="email" value="244594537@qq.com"/>
<property name="gender" value="男"/>
<property name="name" value="吴孟达"/>
</bean>
</beans>
3.测试类:
public class Test {
public static void main(String[] args) {
System.out.println("启动spring容器....");
ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");--------->启动spring的配置文件
System.out.println("spring容器启动成功!");
Person person= (Person) ioc.getBean("person01");----------->此处的person01为spring配置文件中的bean的id
System.out.println(person);
}
}
输出:
启动spring容器....
person的构造器!
设置person的age
设置person的email
设置person的gender
设置pserson的name
spring容器启动成功!
Person{name='吴孟达', age=18, gender='男', email='244594537@qq.com'} 结论:------>发现其执行顺序为:
1.<bean...>元素驱动spring容器调用构造器创建对象
2.<property...>元素驱动spring执行setter方法
如果一个实体类中引用了其他实体类,容器加载的执行顺序
1.第一种情况:范围大的(person引用book)在范围小的前面
spring配置文件内容:
<bean id="person01" class="entity.Person">
<property name="age" value="18"></property>
<property name="name" value="吴孟达"></property>
<property name="book" ref="book"/>
</bean>
<bean id="book" class="entity.Book">
<property name="name" value="java分析"/>
<property name="price" value="32"/>
</bean>
实体类信息:
。。。
测试类信息:
public static void main(String[] args) {
System.out.println("加载spring....");
ApplicationContext ac=new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("spring容器启动成功!");
Person person= (Person) ac.getBean("person01");
System.out.println(person.toString());
}
输出:
加载spring....
person实例化!
Book实例化!
Book执行set name方法
Book执行set price方法
person执行set age方法
person执行set name方法
spring容器启动成功!
发现执行顺序为:
1.先实例化两个对象
2.在执行小的set方法
3.再执行大的set方法 第二种情况:小范围的在上
spring配置文件内容:
<bean id="book" class="entity.Book">
<property name="name" value="java分析"/>
<property name="price" value="32"/>
</bean>
<bean id="person01" class="entity.Person">
<property name="age" value="18"></property>
<property name="name" value="吴孟达"></property>
<property name="book" ref="book"/>
</bean>
输出:
Book实例化!
Book执行set name方法
Book执行set price方法
person实例化!
person执行set age方法
person执行set name方法
spring容器启动成功!
执行顺序为:
1.小范围对象实例化
2.小范围对象set方法
3.大范围对象实例化
4.大范围对象set方法

2.源码解析

1.
以此为示例:
<bean id="book" class="entity.Book"></bean>
实际上<bean.../>元素默认一反射的方式来调用该类的无参构造器
底层简单源码如下:
String idStr=...;//解析<bean。。。。/>元素的id属性得到该字段的字符串值为"book"
String classStr=...;//解析class属性得到该字段的值为:entity.Book
Class clazz=Class.forName(classStr);
Object object=clazz.newInstance();//通过反射示例化对象
container.put(idstr,obj);//将对象放入容器给中,container为spring容器 2.
<bean id="person01" class="entity.Person">
<property name="book" ref="book"/>
</bean>
底层的简单源码如下:
String nameStr=...;解析<property.../>元素的name属性得到该字符串的值为book
String refStr=..;解析<property.../>元素的ref属性得到该字符串的值为book
String setterName-"set"+nameStr.subString(0,1).toUpperCase()+name.subString(1);//生成将要调用的setter方法】
Object paramBean=container.get(refStr);//从容器中取到refStr的bean,作为传入参数
Method setter=clazz.getMethod(setterName,parmBean.getClass())//此处的clazz和1的对应起来
setter.incoke(obj,parmBean);//此处的obj和1的对应起来

3.组件在spring容器中是单例的

public static void main(String[] args) {
System.out.println("加载spring....");
ApplicationContext ac=new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("spring容器启动成功!");
Person person1= (Person) ac.getBean("person01");
Person person2= (Person) ac.getBean("person01");
System.out.println(person1==person2);------------------------->此时输出为true;
}

4.使用构造器为bean的属性赋值

spring配置文件为:
<bean id="book" class="entity.Book">
<property name="name" value="java分析"/>
<property name="price" value="32"/>
</bean>
<bean id="person01" class="entity.Person">-------------------------------->此处有两个person的bean:这一个使用set方法给属性赋值,调用的是无参构造器
<property name="age" value="18"></property>
<property name="name" value="吴孟达"></property>
<property name="book" ref="book"/>
</bean>
<bean id="person02" class="entity.Person">------------------------------>这里调用的是有参构造器来进行属性赋值
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="book" ref="book"></constructor-arg>
<constructor-arg name="name" value="吴孟达02"></constructor-arg>
</bean>
person类的代码:
public class Person {
private String name;
private Integer age;
private Book book;
public Person() {
System.out.println("person执行无参构造器");
}
public Person(String name, Integer age, Book book) {
this.name = name;
this.age = age;
this.book = book;
System.out.println("person执行有参构造器");
}
get/set方法
}
测试类方法:
public static void main(String[] args) {
System.out.println("加载spring....");
ApplicationContext ac=new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("spring容器启动成功!");
Person person= (Person) ac.getBean("person02");
System.out.println(person.toString());
}
输出:
加载spring...
Book实例化!
Book执行set name方法
Book执行set price方法
person执行无参构造器-------------->调用无参构造器实例化对象,然后调用set方法赋值
person执行set age方法
person执行set name方法
person执行有参构造器-------------->调用有参构造器,并且直接赋值
spring容器启动成功!
Person{name='吴孟达02', age=18, book=Book{name='java分析', price=32}}

5.使用p名称空间为bean属性赋值

1.在spring的xml文件中加入这一句:xmlns:p="http://www.springframework.org/schema/p"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"----------------------------------->加入这一句
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="book" class="entity.Book">
<property name="name" value="java分析"/>
<property name="price" value="32"/>
</bean>
<bean id="person03" class="entity.Person" p:age="18" p:name="吴孟达03" p:book-ref="book"></bean>------>此时可以通过p标签进行赋值
</beans>

6.复杂赋值

1.给属性赋值null
<bean id="person04" class="entity.Person">
<property name="name">
<null></null>---------------------------->使用null标签进行赋值:不能使用<property name="name" value="null">这是付了一个null的字符串
</property>
</bean> 2.属性是引用时
2.1引用外部bean
<bean id="book" class="entity.Book">
<property name="name" value="java分析"/>
<property name="price" value="32"/>
</bean>
<bean id="person04" class="entity.Person">
<property name="name">
<null></null>
</property>
<property name="book" ref="book"></property>------------->如果外边已经有了像引用的Book bean,则使用ref引用:这里意思是:book=ioc.getBean("book")
</bean>
测试代码:
ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
Person person= (Person) ioc.getBean("person04");
System.out.println(ioc.getBean("book")==person.getBook());------------->此时输出为true
2.2内部引用
<bean id="person04" class="entity.Person">
<property name="name">
<null></null>
</property>
<property name="book">
<!--对象我们可以使用bean标签创建 book=new Book();引用内部bean-->
<bean class="entity.Book">---------------------------------------->此处需要注意的是:内部bean不能直接通过ioc容器获取:
<property name="name" value="java"></property> ----->如<bean id="bookInner" class="entity.Book">内部bean加上id
<property name="price" value="25"></property> ------>ioc.getBean("bookInner")会获取出错!
</bean>
</property>
</bean>
测试代码为:
ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
Person person= (Person) ioc.getBean("person04");
System.out.println(ioc.getBean("book")==person.getBook());------------->此时输出为false 3.为list属性赋值
为psrson新增属性
private List<Book> library;
如何为library赋值
<property name="library">
<!--library=new ArrayLiast<Book>-->
<list>-------------------------------->使用过list标签
<bean class="entity.Book" p:name="java" p:price="14"></bean>------>1.用bean标签创建list元素
<ref bean="book"></ref>-------------------------------------------->2.用ref标签引入外部bean
</list>
</property> 4.为map赋值
为person新增一个属性
private Map map;
springxml中的配置
<property name="map">
<map>-------------------------------------------->使用map标签:map=new HashMap<>();
<entry key="key01" value="张三"></entry>
<entry key="key02" value="18"></entry>
<entry key="book01" value-ref="book"></entry>----->可以使用value-ref引入外部bean
<entry key="key04">
<bean class="entity.Person" p:name="吴孟达" p:age="18" p:book-ref="book"></bean>------>也可以使用该方式引入内部bean
</entry>
<entry key="key05">---->map中嵌套map
<map> </map>
</entry>
</map>
</property> 5.为Properties赋值
person新增一个属性:
private Properties properties;
spring的配置文件中:
<property name="properties">
<!--properties=new Properties();所有的k=v都是String-->
<props>
<!--k=v都是string,值直接写在标签中-->
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property> 6.使用util名称空间创建集合类型的bean
使用场景:如果相同的map或者list在多处都有引用
可以将map或list单独拿出来做个bean
使用步骤
1.在spring的配置文件中加入:xmlns:util="http://www.springframework.org/schema/util"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"---------------------->在spring的配置文件中加入这行
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
。。。。。
</bean>
2.
<!--相当于new LinkedHashMap<>()-->
<util:map id="mymap">
<!--往map中添加元素-->
<entry key="key01" value="张三"></entry>
<entry key="key02" value="18"></entry>
<entry key="book01" value-ref="book"></entry>
<entry key="key04">
<bean class="entity.Person" p:name="吴孟达" p:age="18" p:book-ref="book"></bean>
</entry>
<entry key="key05">
<map></map>
</entry>
</util:map>
3.其他地方的使用
<property name="map" ref="mymap"></property>----->直接根据引用获取即可
也可以在代码中直接获取
Map<String,Object> map= (Map<String, Object>) ioc.getBean("mymap"); 7.util:list的使用和list标签类似
<util:list id="mylist">
<bean class="entity.Person" p:book="西游" p:name="吴孟达"></bean>
<ref bean="mymap"></ref>
<value>12</value>
</util:list>

8.级联属性:属性的属性
<bean id="book" class="entity.Book">
<property name="name" value="java分析"/>
<property name="price" value="32"/>
</bean>
<bean id="person05" class="entity.Person">
<property name="book" ref="book"></property>
<property name="book.price" value="1000"></property>
----->这里通过book.price直接更改:person的book属性的price属性:但这里注意的是这里一改,容器中的book的bean的price属性改为1000
</bean> 9.通过继承实现bean属性的重用
<bean id="person01" class="entity.Person">
<property name="age" value="18"></property>
<property name="name" value="吴孟达"></property>
<property name="book" ref="book"/>
</bean>
这里需要一个personbean,其他属性都一样,只有age属性变为19,则可以这样
<bean id="person06" class="entity.Person" parent="person01">--------->使用parent属性,指定需要继承属性的bean id,这里的继承只是当前bean的配置信息继承,并不是真正的类继承
<property name="name" value="刘丹"></property>
</bean>
结论:
1. 这里的person01和pserson06在容器中是不同的组件(对象)
2.这两个组件的属性都相同,只有name属性值不同
3.因为指定了要继承配置信息的类,所以上述还可以这样写
<bean id="person06" parent="person01">-------------------------->省略了class,因为配置信息继承于person01,所以class配置值可以继承person01的class配置值值
<property name="name" value="刘丹"></property>
</bean>
4.父类的信息不会因为子类而更改!
10.专门建立一个供其他bean继承的bean
<bean id="person01" class="entity.Person" abstract="true">----------------------->加入:abstract="true"
<property name="age" value="18"></property>
<property name="name" value="吴孟达"></property>
<property name="book" ref="book"/>
</bean>
abstract="true"这个bean的配置是一个抽象的,不能获取他的实例,只能被别人继承
此时:
ioc.getBean("person01");-------------------->此时获取会报错,因为这个是被其他bean继承的

7.bean的作用域

1.单例:scope="singleton"
<bean id="person05" class="entity.Person" scope="singleton">
<property name="book" ref="book"></property>
<property name="book.price" value="1000"></property>
</bean>
2.多例:scope="prototype"
<bean id="person05" class="entity.Person" scope="prototype">
<property name="book" ref="book"></property>
<property name="book.price" value="1000"></property>
</bean>
结论:
1.scope="singleton"单例模式:默认
1.1在容器启动完成前就已经创建好对象,保存在容器中
1.2任何获取都是获取之前创建好的对象
2.scope="prototype"多例模式
2.1容器启动默认不会创建多例的bean
2.2每次获取的时候创建这个bean(ioc.getBean("person05"))
2.3每次获取都会创建一个新的对象

8.bean的生命周期(自定义初始化方法和销毁方法)

1.当是单例模式
1.person实体类
public class Person {
//person的无参构造器
public Person() {
System.out.println("person的无参构造器方法...");
}
//自定义初始化方法
public void initMethod(){
System.out.println("person的初始化方法");
}
//自定义对象销毁方法
public void destroyMethod(){
System.out.println("person的销毁方法");
}
}
2.spring的配置文件
<bean id="person" class="entity.Person"
init-method="initMethod"--------------------------->指定自定义的初始化方法
destroy-method="destroyMethod"--------------------->指定自定义的销毁方法
>
</bean>
3.测试类
public static void main(String[] args) {
System.out.println("spring容器启动...");
ConfigurableApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("spring容器启动成功!");
System.out.println("关闭spring容器...");
ioc.close();---------------------------------------->调用容器的停止方法
System.out.println("关闭spring容器成功!");
}
输出:
spring容器启动...
person的无参构造器方法...
person的初始化方法
spring容器启动成功!
关闭spring容器...
person的销毁方法
关闭spring容器成功! 2.当是多例模式
2.1ioc的配置文件
<bean id="person" class="entity.Person"
scope="prototype"---------------------------->多例模式
init-method="initMethod"
destroy-method="destroyMethod"
>
</bean>
测试代码:
public static void main(String[] args) {
System.out.println("spring容器启动...");
ConfigurableApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("spring容器启动成功!");
System.out.println("关闭spring容器...");
ioc.close();
System.out.println("关闭spring容器成功!");
}
输出:
spring容器启动...
spring容器启动成功!
关闭spring容器...
关闭spring容器成功!
因为多例模式不是容器启动的时候创创建,而是在ioc.getBean("id")时候创建该对象! 2.2当测试代码为:
public static void main(String[] args) {
System.out.println("spring容器启动...");
ConfigurableApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("spring容器启动成功!");
ioc.getBean("person");------------------------>多例模式获取bean对象
System.out.println("关闭spring容器...");
ioc.close();
System.out.println("关闭spring容器成功!");
}
输出:
spring容器启动...
spring容器启动成功!
person的无参构造器方法...
person的初始化方法
关闭spring容器...
关闭spring容器成功! 结论:
1.当是单例模式时:Bean的生命周期
(容器启动)构造器方法---->初始化方法----->(容器关闭)销毁方法
2.多实例
获取bean(构造器------>初始化方法---->容器关闭(不会调用销毁方法))

9.Bean的后置处理器

1.自定义一个类实现BeanPostProcessor接口
public class MyBeanPostProcess implements BeanPostProcessor {
/**
* 自定义的初始化方法之前调用
* Object o是容器创建的bean
* String s是spring配置文件中配置的id
*/
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("bean的后置处理器Befor...方法");
System.out.println(s+":"+o);
return o;----->注意:这里不能return null,要不会报错
}
//自定义初始化方法之后执行
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("bean的后置处理器After...方法");
System.out.println(s+":"+o);
return o;------------------------->注意:这里如果return null;则ioc.getBean也是为null;
}
}
2.在spring配置文件中配置后置处理器
<!--实体类配置-->
<bean id="person01" class="entity.Person"
init-method="initMethod"----------------------->perosn类的自定义初始化方法(person实例化时后会调用)
destroy-method="destroyMethod">----------------->person类的自定义销毁方法(spring容器销毁前会调用)
<property name="age" value="18"></property>
<property name="name" value="吴孟达"></property>
</bean>
<!--后置处理器配置-->
<bean id="myBeanPostProcess" class="Test.MyBeanPostProcess"></bean>
3.测试代码如下:
public static void main(String[] args) {
System.out.println("加载spring....");
ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("spring容器启动成功!");
Object bean= ioc.getBean("person01");
System.out.println("容器获取的bean:"+bean);
}
4.输出:
person执行无参构造器
person执行set age方法
person执行set name方法
bean的后置处理器Befor...方法
person01:Person{name='吴孟达', age=18, book=null}
person自定义的初始化方法
bean的后置处理器After...方法
person01:Person{name='吴孟达', age=18, book=null}
spring容器启动成功!
容器获取的bean:Person{name='吴孟达', age=18, book=null}
结论:
发现带后置处理器的执行流程如下:

执行顺序:

  • 1.bean实例化
  • 2.执行bean的后置处理器的postProcessBeforeInitialization方法
  • 3.执行自定义的初始化方法
  • 4.执行bean后置处理器的postProcessAfterInitialization方法

1.sprng 简介的更多相关文章

  1. ASP.NET Core 1.1 简介

    ASP.NET Core 1.1 于2016年11月16日发布.这个版本包括许多伟大的新功能以及许多错误修复和一般的增强.这个版本包含了多个新的中间件组件.针对Windows的WebListener服 ...

  2. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  3. Cassandra简介

    在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...

  4. REST简介

    一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式.”但是在要求详细讲述它所提出的各个约束,以及如何开始搭建REST服务时,却很少有人能够清晰地说出它到底是什么,需要遵守什么样的准则. ...

  5. Microservice架构模式简介

    在2014年,Sam Newman,Martin Fowler在ThoughtWorks的一位同事,出版了一本新书<Building Microservices>.该书描述了如何按照Mic ...

  6. const,static,extern 简介

    const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...

  7. HTTPS简介

    一.简单总结 1.HTTPS概念总结 HTTPS 就是对HTTP进行了TLS或SSL加密. 应用层的HTTP协议通过传输层的TCP协议来传输,HTTPS 在 HTTP和 TCP中间加了一层TLS/SS ...

  8. 【Machine Learning】机器学习及其基础概念简介

    机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  9. Cesium简介以及离线部署运行

    Cesium简介 cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎,一款开源3DGIS的js库.cesium支持3D,2D,2.5D形式的地图展示,可以自行绘制图形,高亮区 ...

随机推荐

  1. 怎样在方法里面得到Request,或者Session?

    直接在方法的形参中声明request,SpringMvc就自动把request对象传入.

  2. WebSQL是什么?

    WebSQL是客户浏览器端的结构化的关系数据库.这是浏览器内部的本地RDBMS,你可以在这个本地RDBMS上执行SQL查询.

  3. Redis报错:DENIED Redis is running in protected mode

    转:Redis使用认证密码登录   Redis默认配置是不需要密码认证的,也就是说只要连接的Redis服务器的host和port正确,就可以连接使用.这在安全性上会有一定的问题,所以需要启用Redis ...

  4. es6零碎记忆

    1:substring 和 substr var str = '0123456789' console.log(str.substring(1)); //123456789 console.log(s ...

  5. javaweb之修改功能

    数据库的修改功能,主要是通过查询,保留之前的数据,得到当前想要修改的页面,并进行修改. 一.dao层 在dao层需要添加两个fangfa,一个查询,一个修改(这是整个dao层,包括之前的增删.浏览) ...

  6. linux vim编辑器使用

    小i 在光标所在行位置停止不动开始写入内容 大I 在光标所在行行首开始写入内容 小a 在光标所在行当前字符后开始写入内容 大A 在光标所在行行尾开始写入内容 小o 在光标所在行下一行开始写入内容 大O ...

  7. sql server学习总结一

    一,数据库的三级模式结构 1.    模式 模式又称逻辑模式或者概念模式,是数据库中全体数据的逻辑结构和特征的描述,一个数据库只有一个模式,模式处于三级结构的中间层. 2.    外模式 外模式又称用 ...

  8. Myeclipse 中怎样更改web项目的访问名

    第一步:在要修改的项目名称上右击选择最下面一列的"prepertise"(属性),进入属性设置界面. 第二步:找到左侧菜单栏的"Myeclipse"中的web项 ...

  9. 利用es6解构赋值快速提取JSON数据;

    直接上代码 { let JSONData = { title:'abc', test:[ { nums:5, name:'jobs' }, { nums:11, name:'bill' } ] } l ...

  10. 小程序容器助力打造企业超级App

    阿拉丁研究院发布<2021 年度小程序互联网发展白皮书>显示,2021 年全网小程序数量已超 700 万,其中微信小程序开发者突破 300 万,DAU 超过 4.5 亿:日均使用次数同比增 ...