Spring学习笔记——AOP(4)
一、学习AOP
1.1 AOP的概述
1.2 AOP思想实现方案
1.3、模拟AOP的基础代码
1.4、AOP的相关概念
二、基于xml配置AOP
2.1 AOP基础入门
2.2、XML方式AOP配置详解
2.3、XML方式AOP原理剖析
三、注解式开发AOP
3.1 注解式开发AOP入门
3.2 AOP注解详细介绍
3.3、注解方式AOP原理解析
四、基于AOP的声明式事务控制
4.1 Spring事务编程概述
4.2 搭建测试环境
4.3 基于XML声明式事务控制
4.4 注解声明式事务控制
一、学习AOP
1.1 AOP的概述
AOP---->面向切面编程
是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象,一个对象包括静态的属性信息,包括动态的方法信息等。而AOP是横向的对不同事物的抽象,属性与属性
、方法与方法
、对象与对象
都可以组成一个切面,而用这种思维去设计编程的方式叫做面向切面编程
1.2 AOP思想实现方案
代理技术: 动态代理技术,在运行期间,对目标方法进行增强,代理对象同名方法内执行原有逻辑或方法的同时可以执行其他的增强逻辑,或者其他对象的方法
1.3、模拟AOP的基础代码
其实在之前学习BeanPostProcessor时,在BeanPostProcessor
的after方法
中使用动态代理对Bean进行了增强,实际存储到单例池singleObjects中的不是当前目标对象本身,而是当前目标对象的代理对象Proxy
,这样在调用目标对象方法时,实际调用的是代理对象Proxy的同名方法,起到了目标方法前后都进行增强的功能,对该方式进行一下优化,将增强的方法提取出去到一个增强类中,且只对com.itheima.service.impl
包下的任何类的任何方法进行增强
pubiic class MyAdvice {
public void beforeAdvice ( ) {
system. out. println ( "beforeAdvice..." ) ;
)
public void afterAdvice ( ) {
System . out. println ( "afterAdvice..." ) ;
}
}
public class MockAopBeanPostProcessor implements BeanPostProcessor , ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public Object postProcessAfterInitialization ( Object bean, String beanName) throws BeansException {
if ( bean. getClass ( ) . getPackage ( ) . getName ( ) . equals ( "com.Smulll.service.Impl" ) ) {
Object beanProxy = Proxy . newProxyInstance (
bean. getClass ( ) . getClassLoader ( ) ,
bean. getClass ( ) . getInterfaces ( ) ,
( Object proxy, Method method, Object [ ] args) -> {
Myadvice myadvice = applicationContext. getBean ( Myadvice . class ) ;
myadvice. before ( ) ;
Object invoke = method. invoke ( bean, args) ;
myadvice. after ( ) ;
return invoke;
} ) ;
return beanProxy;
}
return null ;
}
@Override
public void setApplicationContext ( ApplicationContext applicationContext) throws BeansException {
this . applicationContext = applicationContext;
}
}
1.4、AOP的相关概念
概念
单词
解释
目标对象
Target
被增强的方法所在的对象
代理对象
Proxy
对目标对象进行增强后的对象,客户端实际调用的对象
连接点
Joinpoint
目标对象中可以被增强的方法
切入点
Pointcut
目标对象中实际被增强的方法
通知\增强
Advice
增强部分的代码逻辑
切面
Aspect
增强和切入点的组合
织入
Weaving
将通知和切入点组合动态组合的过程
二、基于xml配置AOP
2.1 AOP基础入门
基本步骤:
导入AOP相关坐标;
< dependency>
< groupId> org.aspectj groupId>
< artifactId> aspectjweaver artifactId>
< version> 1.9.6 version>
dependency>
准备目标类、准备通知类,并配置给Spring管理;
配置切点表达式(哪些方法被增强);
配置织入(切点被哪些通知方法增强,是前置增强还是后置增强)。
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xmlns: aop= " http://www.springframework.org/schema/aop"
xsi: schemaLocation= "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
" >
< bean id = " userService" class = " com.huanglei.service.Impl.UserServiceImpl" > bean>
< bean id = " myadvice" class = " com.huanglei.advice.Myadvice" > bean>
< aop: config>
< aop: pointcut id = " mtPointcut" expression = " execution(void com.Smulll.service.Impl.UserServiceImpl.show1())" />
< aop: aspect ref = " myadvice" >
< aop: before method = " before" pointcut-ref = " mtPointcut" > aop: before>
< aop: after method = " after" pointcut-ref = " mtPointcut" > aop: after>
aop: aspect>
aop: config>
beans>
2.2、XML方式AOP配置详解
xml配置AOP的方式还是比较简单的,下面看一下AOP详细配置的细节:
< ! -- 配置aop-- >
< aop: config>
< ! -- 配置切点表达式 目的:指定哪些方法被增强-- >
< aop: pointcut id= "mtPointcut" expression= "execution(void com.huanglei.service.Impl.UserServiceImpl.show1())" / >
< aop: pointcut id= "mtPointcut2" expression= "execution(void com.huanglei.service.Impl.UserServiceImpl.show2())" / >
< / aop: config>
pointcut属性可以再后面直接写上要结合的切点
< ! -- 配置aop-- >
< aop: config>
< ! -- 配置切点表达式 目的:指定哪些方法被增强-- >
< aop: pointcut id= "mtPointcut" expression= "execution(void com.huanglei.service.Impl.UserServiceImpl.show1())" / >
< ! -- 配置织入 目的:指定哪些切点与哪些通知结合-- >
< aop: aspect ref= "myadvice" >
< aop: before method= "before" pointcut- ref= "mtPointcut" > < / aop: before>
< aop: after method= "after" pointcut= "execution(void com.huanglei.service.Impl.UserServiceImpl.show1())" > < / aop: after>
< / aop: aspect>
< / aop: config>
切点表达式的配置语法
execution ( [ 访问修饰符] 返回值类型 包名. 类名. 方法名( 参数) )
详解:
访问修饰符可以省略不写;
返回值类型、某一级包名、类名、方法名可以使用*表示任意;
包名与类名之间使用单点.表示该包下的类,使用双点…表示该包及其子包下的类;
参数列表可以使用两个点…表示任意参数。
常见的切点表达式:
execution ( public void com. itheima. aop. TargetImpl. show ( ) )
execution ( * com. itheima. aop. TargetImpl. *( . . ) )
execution ( * com. itheima. aop. *. *( . . ) )
execution ( * com. itheima. aop. . *. *( . . ) )
execution ( * * . . *. *( . . ) )
通知名称
配置方式
执行时机
前置通知
目标方法执行之前执行
后置通知
目标方法执行之后执行,目标方法异常时,不在执行
环绕通知
目标方法执行前后执行,目标方法异常时,环绕后方法不在执行
异常通知
目标方法抛出异常时执行
最终通知
不管目标方法是否有异常,最终都会执行
通知方法再被调用时,Spring可以为其传递一些必要的参数
参数类型
作用
JoinPoint
连接点对象,任何通知都可使用,可以获得当前目标对象、目标方法参数等信息
ProceedingJoinPoint
JoinPoint子类对象,主要是在环绕通知中执行proceed(),进而执行目标方法
Throwable
异常对象,使用在异常通知中,需要在配置文件中指出异常对象名称
public void 通知方法名称( JoinPoint joinPoint) {
system. out. println ( joinPoint. getArgs ( ) ) ;
system. out. println ( joinPoint. getTarget ( ) ) ;
System . out. println ( joinPoint. getstaticPart ( ) ) ;
}
Throwable对象
public void afterThrowing ( JoinPoint joinPoint, Throwable th) {
System . out. println ( "异常对象是:" + th+ "异常信息是:" + th. getMessage ( ) ) ;
}
< aop: after- throwing method= "afterThrowing" pointcut- ref= "myPointcut" throwing= "th" / >
spring定义了一个Advice接口,实现了该接口的类都可以作为通知类出现
public interface Advice {
}
2.3、XML方式AOP原理剖析
动态代理的实现的选择,在调用getProxy()方法时,我们可选用的AopProxy接口有两个实现类,如上图,这两种都是动态生成代理对象的方式,一种就是基于JDK的,一种是基于Cglib的
代理技术
使用条件
配置方式
JDK动态代理技术
目标类有接口,是基于接口动态生成实现类的代理对象
目标类有接口的情况下,默认方式
Cglib 动态代理技术
目标类无接口且不能使用final修饰,是基于被代理对象动态生成子对象为代理对象
目标类无接口时,默认使用该方式;目标类有接口时,手动配置
Target target = new Target ( ) ;
Advices advices = new Advices ( ) ;
Enhancer enhancer = new Enhancer ( ) ;
enhancer. setSuperclass ( Target . class ) ;
enhancer. setCallback ( ( MethodInterceptor ) ( o, method, objects, methodProxy) -> {
advices. before ( ) ;
object result = method. invoke ( target, objects) ;
advices. afterReturning ( ) ;
return result;
} ) ;
Target tagetProxy = ( Target ) enhancer. create ( ) ;
String result = targetProxy. show ( "haohao" ) ;
三、注解式开发AOP
3.1 注解式开发AOP入门
Spring的AOP也提供了注解方式配置,使用相应的注解替代之前的xml配置,xml配置AOP时,我们主要配置了三部分:目标类被Spring容器管理、通知类被Spring管理、通知与切点的织入(切面),如下:
< bean id = " target" class = " com.itheima.aop.TargetImpl" > bean>
< bean id = " advices" class = " com.itheima.aop.Advices" > bean>
< aop: config proxy-target-class = " true" >
< aop: aspect ref = " advices" >
< aop: around method = " around" pointeut = " execution(* com.itheima.aop.*.*(..))" />
aop: aspect>
aop: config>
配置aop,其实配置aop主要就是配置通知类中的哪个方法(通知类型)对应的切点表达式是什么:
注解@Aspect、@Around需要被Spring解析,所以在Spring核心配置文件中需要在配置文件当中添加的自动代理
< aop: aspectj-autoproxy>
3.2 AOP注解详细介绍
通过不同的注解去完成各项通知类型:
@Before ( "execution( *com. itheima.aop.*.*(..))" )
public void before ( JoinPoint joinPoint) { }
@AfterReturning ( "execution(* com.itheima.aop.*.*(..))" )
public void afterReturning ( JoinPoint joinPoint) { }
@Around ( "execution (* com.itheima.aop.*.*(..))" )
public void around ( ProceedingJoinPoint joinPoint) throws Throwable { }
@AfterThrowing ( "execution(* com.itheima.aop.*.*(..))" )
public void afterThrowing ( JoinPoint joinPoint) { }
@After ( "execution(* com.itheima.aop.*.*(..))" )
public void after ( JoinPoint joinPoint) { }
3.3、注解方式AOP原理解析
之前在使用xml配置AOP时,是借助的Spring的外部命名空间的加载方式完成的,使用注解配置后,就抛弃了标签,而该标签最终加载了名为AspectJAwareAdvisorAutoProxyCreator的BeanPostProcessor ,最终,在该BeanPostProcessor中完成了代理对象的生成。
同样,从aspectj-autoproxy标签的解析器入手
this . registerBeanDefinitionParser ( "aspectj-autoproxy" , new AspectJAutoProxyBeanDefinitionParser ( ) ) ;
四、基于AOP的声明式事务控制
4.1 Spring事务编程概述
事务在开发的时候是必不可少的东西,在使用JDBC开发的时候,我们使用的是connection
对事物进行控制,使用Mybatis时,我们使用的时SqlSession对事物进行控制,缺点显而易见,我们在切换数据库访问技术的时候,事务控制的方式就会总是在改变,Spring就在这些技术的基础上,提供了统一的控制事务的接口。Spring的事务分为:编程式事务控制
和声明式事务控制
事务控制的方式
解释
编程式事务控制
Spring提供了事务控制的类和方法,使用编码的方式对业务代码进行了事务控制,事务控制的代码和业务操作代码耦合在一起,在开发当中很少使用
声明式事务控制
Spring提供了事务控制的封装,对外提供了xml配置和注解式开发的配置方式,可以通过配置的方式完成对事物的控制,可以达到事务控制和业务操作代码的解耦合,在开发当中推荐使用
Spring事务编程相关的类:
事务控制相关的类
解释
平台事务管理器 PlatformTransactionManager
是一个接口标准,实现类都具备事务提交、回滚和获得事务对象的功能,不同持久层框架可能会有不同实现方案
事务定义 TransactionDefinition
封装事务的隔离级别、传播行为、过期时间等属性信息
事务状态 TransactionStatus
存储当前事务的状态信息,如果事务是否提交、是否回滚、是否有回滚点等
虽然我们在开发当中不怎么使用这个编程式事务控制,但是对于这个编程式事务控制的相关类我们需要了解一下,因为我们在进行声明式配置的时候我们还会看见他们
4.2 搭建测试环境
搭建一个转账的环境,dao层一个转出钱的方法,一个转入钱的方法service层一个转账业务方法,内部分别调 用dao层转出钱和转入钱的方法,准备工作如下:
数据库准备一个账户表tb_account;
dao层准备一个AccountMapper,包括incrMoney和decrMoney两个方法;
service层准备一个transferMoney方法,分别调用incrMoney和decrMoney方法;
在applicationContext文件中进行Bean的管理配置;
测试正常转账与异常转账。
xml配置:
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xmlns: cotext= " http://www.springframework.org/schema/context"
xmlns: aop= " http://www.springframework.org/schema/aop"
xsi: schemaLocation= "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
" >
< cotext: component-scan base-package = " com.huanglei" />
< cotext: property-placeholder location = " classpath:jdbc.properties" />
< bean id = " dataSource" class = " com.alibaba.druid.pool.DruidDataSource" >
< property name = " driverClassName" value = " ${jdbc.driver}" />
< property name = " url" value = " ${jdbc.url}" />
< property name = " username" value = " ${jdbc.username}" />
< property name = " password" value = " ${jdbc.password}" />
bean>
< bean class = " org.mybatis.spring.SqlSessionFactoryBean" >
< property name = " dataSource" ref = " dataSource" > property>
bean>
< bean class = " org.mybatis.spring.mapper.MapperScannerConfigurer" >
< property name = " basePackage" value = " com.huanglei.mapper" > property>
bean>
beans>
Mapper映射文件
public interface accountMapper {
@Update ( "update tb_account set money = money+#{money} where account_name = #{accountName}" )
public void incrMoney ( @Param ( "accountName" ) String accountName, @Param ( "money" ) Double money) ;
@Update ( "update tb_account set money = money-#{money} where account_name = #{accountName}" )
public void decrMoney ( @Param ( "accountName" ) String accountName, @Param ( "money" ) Double money) ;
}
service代码:
@Service ( "accountService" )
public class AccountServiceImpl implements AccountService {
@Autowired
private accountMapper accountMapper;
public void transferMoney ( String outAccount, String inAccount, Double money) {
accountMapper. decrMoney ( outAccount, money) ;
accountMapper. incrMoney ( inAccount, money) ;
}
}
4.3 基于XML声明式事务控制
结合我们学过的AOP技术,我们可以使用AOP对service的方法进行事务增强。
目标类:自定义的AccountServicelmpl,内部的方法是切点
通知类: Spring提供的,通知方法已经定义好,只需要配置即可
通知类是Spring提供的,需要导入Spring事务的相关的坐标;
配置目标类AccountServicelmpl;
使用advisor标签配置切面。
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xmlns: cotext= " http://www.springframework.org/schema/context"
xmlns: aop= " http://www.springframework.org/schema/aop"
xmlns: tx= " http://www.springframework.org/schema/tx"
xsi: schemaLocation= "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
" >
< cotext: component-scan base-package = " com.huanglei" />
< cotext: property-placeholder location = " classpath:jdbc.properties" />
< bean id = " dataSource" class = " com.alibaba.druid.pool.DruidDataSource" >
< property name = " driverClassName" value = " ${jdbc.driver}" />
< property name = " url" value = " ${jdbc.url}" />
< property name = " username" value = " ${jdbc.username}" />
< property name = " password" value = " ${jdbc.password}" />
bean>
< bean class = " org.mybatis.spring.SqlSessionFactoryBean" >
< property name = " dataSource" ref = " dataSource" > property>
bean>
< bean class = " org.mybatis.spring.mapper.MapperScannerConfigurer" >
< property name = " basePackage" value = " com.huanglei.mapper" > property>
bean>
< bean id = " transactionManager" class = " org.springframework.jdbc.datasource.DataSourceTransactionManager" >
< property name = " dataSource" ref = " dataSource" />
bean>
< tx: advice id = " txAdvice" transaction-manager = " transactionManager" >
< tx: attributes>
< tx: method name = " *" />
tx: attributes>
tx: advice>
< aop: config>
< aop: pointcut id = " txPointcut" expression = " execution(* com.Smulll.service.Impl.*.*(..))" />
< aop: advisor advice-ref = " txAdvice" pointcut-ref = " txPointcut" />
aop: config>
beans>
< tx: advice id = " txAdvice" transaction-manager = " transactionManager" >
< tx: attributes>
< tx: method name = " *" isolation = " READ_COMMITTED" propagation = " " timeout = " 3" read-only = " false" />
tx: attributes>
tx: advice>
**isolation属性:**指定了事务的隔离级别,事务并发存在三大问题:脏读,不可重复读,幻读/虚度
。可以通过设置事务的隔离级别来保证并发问题的实现,常用的是READ_COMMITTED和REPEATABLE_READ
常见的isolation设置:
isolation属性
解释
DEFAULT
表示的为默认的隔离级别,这个取决于你使用的哪种数据库,如MySQL就是REPEATABLE_READ
READ_UNCOMMITTED
A事务可以读取到B事务尚未提交的事务记录,不能解决任何并发问题,安全性最低,性能最高
READ_COMMITTED
A事务只能读取到其他事务已经提交的记录,不能读取到未提交的记录。可以解决脏读问题,但是不能解决不可重复读和幻读
REPEATABLE_READ
A事务多次从数据库读取某条记录结果一致,可以解决不可重复读,不可以解决幻读
SERIALIZABLE
串行化,可以解决任何并发问题,安全性最高,但是性能最低
**read-only属性:**就是设置当前的状态,为只读还是可以修改。设置为true表示只读,那么这样可以提高查询的性能,如果要增加或者删除修改,那必须得设置为法false
< tx: method name = " select*" read-only = " true" />
< tx: method name = " find*" read-only = " false" />
**timeout属性:**设置事务提交的最长时间,如果超过这个时间那么事务就会自动回滚,不再执行。默认值为-1,表示没有时间限制。
< tx: method name = " select*" read-only = " true" timeout = " 3" />
propagation属性 :设置事务的传播行为,主要解决是A方法调用B方法时,事务的传播方式问题的,例如:使用单方的事务,还是A和B都使用自己的事务等。事务的传播行为有如下七种属性值可配置
事务传播的行为
解释
REQUIRED (默认值)
A调用B,B需要事务,如果A有事务B就加入A的事务中,如果A没有事务,B就自己创建一个事务
REQUIRED_NEW
A调用B,B需要新事务,如果A有事务就挂起,B自己创建一个新的事务
SUPPORTS
A调用B,B有无事务无所谓,A有事务就加入到A事务中,A无事务B就以非事务方式执行
NOT_SUPPORTS
A调用B,B有无事务无所谓,A有事务就加入到A事务中,A无事务B就以非事务方式执行
NEVER
A调用B,B以无事务方式执行,A如有事务则抛出异常
MANDATORY
A调用B,B要加入A的事务中,如果A无事务就抛出异常
NESTED
A调用B, B创建一个新事务,A有事务就作为嵌套事务存在,A没事务就以创建的新事务执行
4.4 注解声明式事务控制
@Configuration
@ComponentScan ( "com.huanglei" )
@PropertySource ( "classpath:jdbc.properties" )
@MapperScan ( "com.huanglei.mapper" )
@EnableTransactionManagement
public class SpringConfig {
@Bean
public DataSource dataSource (
@Value ( "${jdbc.driver}" ) String driver,
@Value ( "${jdbc.url}" ) String url,
@Value ( "${jdbc.username}" ) String username,
@Value ( "${jdbc.password}" ) String password
) {
DruidDataSource dataSource = new DruidDataSource ( ) ;
dataSource. setDriverClassName ( driver) ;
dataSource. setUrl ( url) ;
dataSource. setUsername ( username) ;
dataSource. setPassword ( password) ;
return dataSource;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean ( DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean ( ) ;
sqlSessionFactoryBean. setDataSource ( dataSource) ;
return sqlSessionFactoryBean;
}
@Bean
public DataSourceTransactionManager transactionManager ( DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager ( ) ;
dataSourceTransactionManager. setDataSource ( dataSource) ;
return dataSourceTransactionManager;
}
}
你可能感兴趣的:(Spring,spring,学习,笔记,后端)
.net core + vue 搭建前后端分离的框架
战族狼魂
C# .netcore
目录步骤一:创建.NETCore后端项目步骤二:创建Vue.js前端项目步骤三:集成后端和前端项目步骤一:创建.NETCore后端项目安装.NETCoreSDK:确保你的开发环境中已安装了最新版本的.NETCoreSDK。你可以从.NET下载页面获取最新版本。创建.NETCoreWebAPI项目:在命令行或者通过VisualStudio等集成开发环境,创建一个新的.NETCoreWebAPI项目。
前后端交互的方式能分为几种
阿贾克斯的黎明
java java
前后端交互主要可以分为以下几类:**一、HTTP请求交互**1.GET请求:用于从服务器获取资源,通常将参数放在URL中进行传递。特点是简单、快速,但不太适合传递大量数据或敏感信息,因为参数会在URL中显示。GET请求:用于获取商品列表、商品详情、用户订单状态等信息。例如,用户浏览商品页面时,前端通过GET请求从服务器获取商品的图片、价格、描述等数据进行展示。2.POST请求:用于向服务器提交数据
【深度学习】softmax回归的简洁实现
熙曦Sakura
深度学习 深度学习 回归 人工智能
softmax回归的简洁实现我们发现(通过深度学习框架的高级API能够使实现)(softmax)线性(回归变得更加容易)。同样,通过深度学习框架的高级API也能更方便地实现softmax回归模型。本节继续使用Fashion-MNIST数据集,并保持批量大小为256。importtorchfromtorchimportnnfromd2limporttorchasd2l初始化模型参数[softmax回
Jenkins部署前后端分离项目最全图文教程(手把手教学)
黄团团
运维 Jenkins Tomcat jenkins 运维 linux 华为云 nginx tomcat maven
前言:最近Jenkins部署的热度比较高,于是就想出一篇关于我是如何使用Jenkins部署前后端分离项目的,本篇记录了我是如何一步一步去配置、搭建和部署的完整流程,每一行代码都进行了实测和讲解,通过图文的教学写成博客分享给大家!博主的其他部署教程:1、Docker部署前后端分离项目:手把手通过Docker部署前后端分离项目(亲测可用)2、Linux系统部署Tomcat:Linux系统部署Tomca
第二篇:多模态技术突破——DeepSeek如何重构AI的感知与认知边界
python算法(魔法师版)
动态规划
——从跨模态对齐到因果推理的工程化实践在AI技术从单一模态向多模态跃迁的关键阶段,DeepSeek通过自研的多模态融合框架,在视觉-语言-语音的联合理解与生成领域实现系统性突破。本文将从技术实现层面,解构其跨模态表征学习、动态融合机制与因果推理能力的内在创新。1.跨模态对齐革命:时空一致性建模传统多模态模型常面临模态割裂问题,DeepSeek提出「时空同步对比学习」(ST-CL)框架:视觉-语言对
蓝桥杯备考:前缀和算法---模板题
无敌大饺子 1
蓝桥杯 职场和发展
【模板】前缀和这道题,如果我们简单的用暴力解法,时间复杂度就是O(q*N)也就是10的十次方,这时候我们就会超时我们要学习一种前缀和的算法,它能帮助我们做一些预处理,用空间复杂度代替时间复杂度,比如说这道题,我们开辟一个数组,f[N],我们只需要一个公式f[i]=f[i-1]+a[i]就能完成我们的预处理,最后查询的时间复杂度就是O(1)了,比如我们要查询l到r的和,我们就让f[r]-f[l-1]
Vue3 结合 .NetCore WebApi 前后端分离跨域请求简易实例
醉の虾
.netcore vue.js 前端
1、本地安装Vue3环境参考:VUE3中文文档-快速上手注意:初始安装vue时,需要安装router,否则后续也要安装2、安装axios组件比如:npminstallaxios@latest或pnpminstallaxios@latest3、设置跨域请求代理打开vue3项目根目录的vite.config.js文件,插入跨域请求设置这样实现的效果,假设你的前端域名是http://localhost:
git如何忽略指定文件以及gitignore相关知识
GL_C
git
git如何忽略指定文件文章概要:本文主要介绍了git中如何忽略指定文件,包括已经commit了的文件。解释了gitignore文件的写法以及提供了常见的gitignore模版。本文内容来自:谷流仓AI-ai.guliucang.com在平常写代码使用git的过程中,我们项目有些文件是不适合提交到仓库的,因此需要让git忽略这些文件,解除对这些文件的跟踪。文末附录部分会附上一些常见的前后端需要忽略的
mac 安装多个python版本
泡了个面
macos python 开发语言
python相关学习资料:https://edu.51cto.com/video/1158.htmlhttps://edu.51cto.com/video/4102.htmlhttps://edu.51cto.com/video/3832.html安装多个Python版本在Mac上的指南作为一名经验丰富的开发者,我经常被问到如何在Mac上安装和管理多个Python版本。这篇文章将详细指导你如何实现
深度学习查漏补缺:1.梯度消失、梯度爆炸和残差块
nnerddboy
白话机器学习 深度学习 人工智能
一、梯度消失梯度消失的根本原因在于激活函数的性质和链式法则的计算:激活函数的导数很小:常见的激活函数(例如Sigmoid和Tanh)在输入较大或较小时,输出趋于饱和(Sigmoid的输出趋于0或1),其导数接近于0。在反向传播中,每一层的梯度都会乘以激活函数的导数。如果导数很小,乘积就会导致梯度逐渐变小。链式法则的多次相乘:假设网络有nn层,梯度从输出层传到第ii层时,会经历多次链式相乘:如果每一
(尚硅谷 Java 学习 B 站大学版)Day 13 面向对象 方法
亢从文_Jackson
java 学习 开发语言
4-5类的成员之二:方法(Method)一、“万事万物皆对象”**:(理解)1、在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构>Scanner,String等>文件:File>网络资源:URL2、涉及到java语言与前端html、后端数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象二、内存解析说明1、引用类型的变量,只可能存储两类值:nu
tensorflow编码错误:TypeError: unsupported operand type(s) for *: ‘float‘ and ‘NoneType‘
Ding_99
tensorflow python
tensorflow编码出现错误:TypeError:unsupportedoperandtype(s)for*:‘float’and‘NoneType’原码如下:importtensorflowastfw=tf.Variable(tf.constant(5,dtype=float))#给w赋随机值,初始值为float5lr=0.2#学习率设为0.2epoch=20#设置循环迭代次数foriinr
跨平台的客户端gui到底是选“原生”还是web
扎量丙不要犟
前端 rust javascript tauri electron qt c++
我们讨论的是客户端的“前端”gui部分是选“原生”还是“web”,而不是讨论客户端用“js”还是“原生”。为什么这么说呢?我们应该把客户端也分为“前端”和“后端”,如果客户端没有“后端”,那么不在讨论范围。我们看一下“前端”的定义:(Front-End)通常指与用户直接交互的部分,即用户看到、操作并与之互动的界面。它涵盖了视觉设计、交互逻辑,主要关注用户体验(UserExperience,UX)和
使用 Go Zero 开发 FPS 游戏后端接口文档
阿贾克斯的黎明
游戏开发 后端
目录使用GoZero开发FPS游戏后端接口文档一、用户管理微服务1.注册接口2.登录接口3.账号信息管理接口二、游戏匹配微服务1.匹配算法接口2.匹配队列接口三、游戏房间管理微服务1.房间创建接口2.房间加入接口3.房间状态管理接口四、游戏逻辑处理微服务1.玩家操作处理接口1.玩家操作处理接口2.碰撞检测接口3.伤害计算接口五、数据存储与管理微服务1.玩家数据存储接口2.游戏数据存储接口错误码与异
从System Prompt来看Claude3、Kimi和ChatGLM4之间的差距
herosunly
大模型 system prompt gpt4 claude kimi ChatGLM4
大家好,我是herosunly。985院校硕士毕业,现担任算法t研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法行业就业。希望和大家一起成长进步。 本文主要介绍了从SystemPrompt来看Claude3、Kimi和ChatGLM
DeepSeek-R1,DeepSeek-V3,DeepSeek-VL,DeepSeek-V2,DeepSeek-R1-Zero各个模型区别
fpga和matlab
前言技术汇集 # 人工智能 大模型 DeepSeek
目录1.各个模型架构2.训练方式3.模型参数与规模4.应用场景5.性能表现6.发布时间7.价格1.各个模型架构DeepSeek-R1:未明确有特殊架构说明,但属于推理模型,可能在Transformer架构基础上针对推理做了优化,通过强化学习训练实现大量反思和验证。DeepSeek-V3:是混合专家(MoE)语言模型,采用Transformer架构。DeepSeek-VL:整体上是decoder-o
如何在springboot中合理使用工厂模式(你真的会在实际业务中应用设计模式吗?)
辞半夏丶北笙
spring boot 设计模式 后端
如何在springboot中合理使用工厂模式-工厂模式工厂模式优点:前言请看如下工程结构实例:1、在工厂中声明的bean如何交给springboot管理方法一:使用Spring的@Bean方法来注册工厂方法方法二:使用Spring的ApplicationContext来获取bean方法三:使用原型bean(推荐)实现代码1、定义组件接口:2、不同的组件实现:3、创建工厂通过抽象工厂注入不同的bea
Python能否实现股票的自动买卖?需要具备哪些技术和条件
股票程序化交易接口
量化交易 股票API接口 Python股票量化交易 python 股票自动买卖 技术条件 券商接口 股票量化接口 股票API接口
Python股票接口实现查询账户,提交订单,自动交易(1)Python股票程序交易接口查账,提交订单,自动交易(2)股票量化,Python炒股,CSDN交流社区>>>Python在股票交易中的基础Python是一种高级编程语言,在股票交易中有诸多优势。它具有简洁的语法,易于学习和编写代码。使用几行简单的Python代码就可以实现数据的读取和初步分析。其丰富的库,如pandas用于数据处理,nump
基于face_recognition的人脸识别
#北极星star
人脸识别 人工智能 opencv 计算机视觉
目录一.简要介绍二.相关函数三.算法流程四.代码实现五.效果展示一.简要介绍face_recognition是一个基于Python的开源人脸识别库,它使用dlib库中的深度学习模型来实现人脸识别功能。这个库以其简洁的API和高效的性能而广受欢迎,成为许多开发者和研究者的首选工具。face_recognition库的主要功能包括:1.人脸检测:识别图像中所有的人脸并返回其位置信息。2.人脸编码:将检
solr 的admin.html 详细使用讲解
qq_37300675
solr
爱雨轩真正的爱情,就像花朵,开放的地方越贫瘠,越是美丽动人!目录视图摘要视图订阅征文|从高考,到程序员深度学习与TensorFlow入门一课搞定!每周荐书|Web扫描、HTML5、Python(评论送书)solr管理界面详解标签:solrsolr管理界面solrqueryanalysis2016-08-0210:425117人阅读评论(0)收藏举报本文章已收录于:分类:Solr(8)作者同类文章X
Web 开发入门:从前端到后端的全栈开发探索
HelloZheQ
前端
Web开发是指创建和维护通过网络浏览器访问的应用程序。Web开发涉及到的领域非常广泛,涵盖了前端、后端、数据库等多个技术栈。在这篇文章中,我们将详细介绍Web开发的基本概念、前端和后端的技术、全栈开发的特点以及如何开始从事Web开发。1.Web开发简介Web开发是构建和维护网站或Web应用程序的过程,分为前端开发、后端开发和全栈开发。前端开发负责用户界面和交互体验,后端开发负责服务器端的逻辑处理、
【数据结构】顺序表的实现——动态分配
豌豆射手^
数据结构 数据结构 java 开发语言
个人主页:豌豆射手^欢迎点赞✍评论⭐收藏收录专栏:数据结构希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步!【数据结构】顺序表的实现——动态分配引言一动态分配内存的概念1.1概念1.2类比二动态分配的步骤2.1工作步骤2.2类比三顺序表的动态分配概念3.1概念3.2类比四顺序表动态分配的具体步骤总结引言在数据结构的领域中,顺序表作为一种基础的线性数据结构,其实现方
requests模块-timeout参数
李乾星
爬虫自学笔记 开发语言 python 网络爬虫 网络协议
超时参数timeout的重要性与使用方法在进行网上冲浪或爬虫项目开发时,我们常常会遇到网络波动和请求处理时间过长的情况。长时间等待一个请求可能仍然没有结果,导致整个项目效率低下。为了解决这个问题,我们可以使用超时参数timeout来强制要求请求在特定时间内返回结果,否则将抛出异常。使用超时参数timeout的方法在学习爬虫和request模块的过程中,我们会频繁使用requests.get(url
人工智能导论--第1章-知识点与学习笔记
想拿高薪的韭菜
人工智能 学习 笔记
请根据教材内容,完成进行下面的作业任务。必须包含有教材的具体内容,不能是生成式AI系统的生成内容。参考教材1.1节的内容介绍,谈谈你对“智能”的认识。思维能力是智能的重要特征之一,结合教材1.1.2节内容,从思维的定义、分类及其特点等角度,阐述思维的含义。参考教材1.1.3节的内容介绍,名词解析“人工智能”。参考教材1.2节的内容介绍,介绍人工智能的发展简史。参考教材1.3节的内容介绍,人工智能作
高效构建仓库AGV管理系统:基于Python的路径规划与货架管理
机器懒得学习
python 开发语言 数据分析 路径规划 AGV
在现代化仓储中,高效管理自动引导车辆(AGV)是提升生产力和管理效率的关键。作为一种智能仓储设备,AGV可以自主完成物料的搬运,但如何实现AGV的路径规划和货架管理?本篇博客将通过一个Python项目,带你深度了解如何实现一个具备路径规划与货架管理功能的仓库管理系统(WMS)。在此过程中,你将学习到AGV的路径规划、图像可视化、节拍管理等核心技术。无论你是对物流技术感兴趣,还是对Python项目管
几种常见的工具类
小裕哥略帅
java 开发语言
反射工具类packagecom.mdgyl.common.util;importorg.springframework.util.StringUtils;importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjava.util.Objects;/***description:反射工具类*author:wuyc*crea
Spring中常见的注解
小裕哥略帅
python 开发语言
1spring注解介绍SpringFramework是一个开源的Java平台,广泛用于创建高性能的企业应用程序。随着Spring的发展,注解(Annotation)已经成为了配置Spring应用程序的主要方式,逐渐取代了传统的XML配置。使用注解可以使代码更加简洁明了,提高开发效率和可读性。Spring的注解驱动的编程模型大大简化了Java企业应用的开发。通过减少配置的复杂性,提高代码的清晰度和模
NotebookLM:Google 最新 AI 笔记助理解析与实战应用
赵大仁
人工智能 技术 大语言模型 深度学习 人工智能 语言模型 自然语言处理 机器学习 笔记
NotebookLM:Google最新AI笔记助理解析与实战应用在AI驱动的生产力工具不断进化的今天,Google推出的NotebookLM(NotebookLanguageModel)成为了一款备受关注的智能笔记助理。它结合了Google的大语言模型(LLM)能力,帮助用户更高效地整理、理解和生成知识内容。本文将全面解析NotebookLM的技术原理、核心功能、应用场景,并提供实际使用指南,帮助
Qt MDI和Ribbon界面集成实践教程
Pella732
本文还有配套的精品资源,点击获取简介:本文深入介绍了基于Qt的RibbonMDIDemo项目,该项目展示了一个具有MicrosoftOffice风格的RibbonBar的多文档界面应用程序。通过一个完整的示例工程,读者可以学习如何在Qt环境中构建Ribbon风格的用户界面以及多文档界面(MDI)的应用程序。教程覆盖了RibbonBar的设计、MDIArea的管理、菜单和工具栏的整合,以及文档和视图
Node+puppeteer学习笔记(九)--使用-Python3 + Pyppeteer
温柔夏目
Puppeteer
因为我是Python流,自动化都是基于Python的,所以一直在关注Puppeteer这个包是否会被Python支持,然后我就在官网上找到了Pyppeteer这个包,因为修改了第二个字母,差点没认出来,这个包其实就是根据Puppeteer实现的地址如下:官方GitHub仓库:https://github.com/miyakogi/pyppeteer.官方API地址:https://miyakogi
解读Servlet原理篇二---GenericServlet与HttpServlet
周凡杨
java HttpServlet 源理 GenericService 源码
在上一篇《解读Servlet原理篇一》中提到,要实现javax.servlet.Servlet接口(即写自己的Servlet应用),你可以写一个继承自javax.servlet.GenericServletr的generic Servlet ,也可以写一个继承自java.servlet.http.HttpServlet的HTTP Servlet(这就是为什么我们自定义的Servlet通常是exte
MySQL性能优化
bijian1013
数据库 mysql
性能优化是通过某些有效的方法来提高MySQL的运行速度,减少占用的磁盘空间。性能优化包含很多方面,例如优化查询速度,优化更新速度和优化MySQL服务器等。本文介绍方法的主要有:
a.优化查询
b.优化数据库结构
ThreadPool定时重试
dai_lm
java ThreadPool thread timer timertask
项目需要当某事件触发时,执行http请求任务,失败时需要有重试机制,并根据失败次数的增加,重试间隔也相应增加,任务可能并发。
由于是耗时任务,首先考虑的就是用线程来实现,并且为了节约资源,因而选择线程池。
为了解决不定间隔的重试,选择Timer和TimerTask来完成
package threadpool;
public class ThreadPoolTest {
Oracle 查看数据库的连接情况
周凡杨
sql oracle 连接
首先要说的是,不同版本数据库提供的系统表会有不同,你可以根据数据字典查看该版本数据库所提供的表。
select * from dict where table_name like '%SESSION%';
就可以查出一些表,然后根据这些表就可以获得会话信息
select sid,serial#,status,username,schemaname,osuser,terminal,ma
类的继承
朱辉辉33
java
类的继承可以提高代码的重用行,减少冗余代码;还能提高代码的扩展性。Java继承的关键字是extends
格式:public class 类名(子类)extends 类名(父类){ }
子类可以继承到父类所有的属性和普通方法,但不能继承构造方法。且子类可以直接使用父类的public和
protected属性,但要使用private属性仍需通过调用。
子类的方法可以重写,但必须和父类的返回值类
android 悬浮窗特效
肆无忌惮_
android
最近在开发项目的时候需要做一个悬浮层的动画,类似于支付宝掉钱动画。但是区别在于,需求是浮出一个窗口,之后边缩放边位移至屏幕右下角标签处。效果图如下:
一开始考虑用自定义View来做。后来发现开线程让其移动很卡,ListView+动画也没法精确定位到目标点。
后来想利用Dialog的dismiss动画来完成。
自定义一个Dialog后,在styl
hadoop伪分布式搭建
林鹤霄
hadoop
要修改4个文件 1: vim hadoop-env.sh 第九行 2: vim core-site.xml <configuration> &n
gdb调试命令
aigo
gdb
原文:http://blog.csdn.net/hanchaoman/article/details/5517362
一、GDB常用命令简介
r run 运行.程序还没有运行前使用 c cuntinue 
Socket编程的HelloWorld实例
alleni123
socket
public class Client
{
public static void main(String[] args)
{
Client c=new Client();
c.receiveMessage();
}
public void receiveMessage(){
Socket s=null;
BufferedRea
线程同步和异步
百合不是茶
线程同步 异步
多线程和同步 : 如进程、线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A再继续操作。 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,同时其它线程也不能调用这个方法
多线程和异步:多线程可以做不同的事情,涉及到线程通知
&
JSP中文乱码分析
bijian1013
java jsp 中文乱码
在JSP的开发过程中,经常出现中文乱码的问题。
首先了解一下Java中文问题的由来:
Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,
js实现页面跳转重定向的几种方式
bijian1013
JavaScript 重定向
js实现页面跳转重定向有如下几种方式:
一.window.location.href
<script language="javascript"type="text/javascript">
window.location.href="http://www.baidu.c
【Struts2三】Struts2 Action转发类型
bit1129
struts2
在【Struts2一】 Struts Hello World http://bit1129.iteye.com/blog/2109365中配置了一个简单的Action,配置如下
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configurat
【HBase十一】Java API操作HBase
bit1129
hbase
Admin类的主要方法注释:
1. 创建表
/**
* Creates a new table. Synchronous operation.
*
* @param desc table descriptor for table
* @throws IllegalArgumentException if the table name is res
nginx gzip
ronin47
nginx gzip
Nginx GZip 压缩
Nginx GZip 模块文档详见:http://wiki.nginx.org/HttpGzipModule
常用配置片段如下:
gzip on; gzip_comp_level 2; # 压缩比例,比例越大,压缩时间越长。默认是1 gzip_types text/css text/javascript; # 哪些文件可以被压缩 gzip_disable &q
java-7.微软亚院之编程判断俩个链表是否相交 给出俩个单向链表的头指针,比如 h1 , h2 ,判断这俩个链表是否相交
bylijinnan
java
public class LinkListTest {
/**
* we deal with two main missions:
*
* A.
* 1.we create two joined-List(both have no loop)
* 2.whether list1 and list2 join
* 3.print the join
Spring源码学习-JdbcTemplate batchUpdate批量操作
bylijinnan
java spring
Spring JdbcTemplate的batch操作最后还是利用了JDBC提供的方法,Spring只是做了一下改造和封装
JDBC的batch操作:
String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
[JWFD开源工作流]大规模拓扑矩阵存储结构最新进展
comsci
工作流
生成和创建类已经完成,构造一个100万个元素的矩阵模型,存储空间只有11M大,请大家参考我在博客园上面的文档"构造下一代工作流存储结构的尝试",更加相信的设计和代码将陆续推出.........
竞争对手的能力也很强.......,我相信..你们一定能够先于我们推出大规模拓扑扫描和分析系统的....
base64编码和url编码
cuityang
base64 url
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
web应用集群Session保持
dalan_123
session
关于使用 memcached 或redis 存储 session ,以及使用 terracotta 服务器共享。建议使用 redis,不仅仅因为它可以将缓存的内容持久化,还因为它支持的单个对象比较大,而且数据类型丰富,不只是缓存 session,还可以做其他用途,一举几得啊。1、使用 filter 方法存储这种方法比较推荐,因为它的服务器使用范围比较多,不仅限于tomcat ,而且实现的原理比较简
Yii 框架里数据库操作详解-[增加、查询、更新、删除的方法 'AR模式']
dcj3sjt126com
数据库
public function getMinLimit () { $sql = "..."; $result = yii::app()->db->createCo
solr StatsComponent(聚合统计)
eksliang
solr聚合查询 solr stats
StatsComponent
转载请出自出处:http://eksliang.iteye.com/blog/2169134
http://eksliang.iteye.com/ 一、概述
Solr可以利用StatsComponent 实现数据库的聚合统计查询,也就是min、max、avg、count、sum的功能
二、参数
百度一道面试题
greemranqq
位运算 百度面试 寻找奇数算法 bitmap 算法
那天看朋友提了一个百度面试的题目:怎么找出{1,1,2,3,3,4,4,4,5,5,5,5} 找出出现次数为奇数的数字.
我这里复制的是原话,当然顺序是不一定的,很多拿到题目第一反应就是用map,当然可以解决,但是效率不高。
还有人觉得应该用算法xxx,我是没想到用啥算法好...!
还有觉得应该先排序...
还有觉
Spring之在开发中使用SpringJDBC
ihuning
spring
在实际开发中使用SpringJDBC有两种方式:
1. 在Dao中添加属性JdbcTemplate并用Spring注入;
JdbcTemplate类被设计成为线程安全的,所以可以在IOC 容器中声明它的单个实例,并将这个实例注入到所有的 DAO 实例中。JdbcTemplate也利用了Java 1.5 的特定(自动装箱,泛型,可变长度
JSON API 1.0 核心开发者自述 | 你所不知道的那些技术细节
justjavac
json
2013年5月,Yehuda Katz 完成了JSON API(英文,中文) 技术规范的初稿。事情就发生在 RailsConf 之后,在那次会议上他和 Steve Klabnik 就 JSON 雏形的技术细节相聊甚欢。在沟通单一 Rails 服务器库—— ActiveModel::Serializers 和单一 JavaScript 客户端库——&
网站项目建设流程概述
macroli
工作
一.概念
网站项目管理就是根据特定的规范、在预算范围内、按时完成的网站开发任务。
二.需求分析
项目立项
我们接到客户的业务咨询,经过双方不断的接洽和了解,并通过基本的可行性讨论够,初步达成制作协议,这时就需要将项目立项。较好的做法是成立一个专门的项目小组,小组成员包括:项目经理,网页设计,程序员,测试员,编辑/文档等必须人员。项目实行项目经理制。
客户的需求说明书
第一步是需
AngularJs 三目运算 表达式判断
qiaolevip
每天进步一点点 学习永无止境 众观千象 AngularJS
事件回顾:由于需要修改同一个模板,里面包含2个不同的内容,第一个里面使用的时间差和第二个里面名称不一样,其他过滤器,内容都大同小异。希望杜绝If这样比较傻的来判断if-show or not,继续追究其源码。
var b = "{{",
a = "}}";
this.startSymbol = function(a) {
Spark算子:统计RDD分区中的元素及数量
superlxw1234
spark spark算子 Spark RDD分区元素
关键字:Spark算子、Spark RDD分区、Spark RDD分区元素数量
Spark RDD是被分区的,在生成RDD时候,一般可以指定分区的数量,如果不指定分区数量,当RDD从集合创建时候,则默认为该程序所分配到的资源的CPU核数,如果是从HDFS文件创建,默认为文件的Block数。
可以利用RDD的mapPartitionsWithInd
Spring 3.2.x将于2016年12月31日停止支持
wiselyman
Spring 3
Spring 团队公布在2016年12月31日停止对Spring Framework 3.2.x(包含tomcat 6.x)的支持。在此之前spring团队将持续发布3.2.x的维护版本。
请大家及时准备及时升级到Spring
fis纯前端解决方案fis-pure
zccst
JavaScript
作者:zccst
FIS通过插件扩展可以完美的支持模块化的前端开发方案,我们通过FIS的二次封装能力,封装了一个功能完备的纯前端模块化方案pure。
1,fis-pure的安装
$ fis install -g fis-pure
$ pure -v
0.1.4
2,下载demo到本地
git clone https://github.com/hefangshi/f