前置通知(Before advice) 在某个连接点(join point)之前执行的通知,但不能阻止连接点前的执行(除非它抛出异常)
返回后通知(After returning advice) 在某个连接点(join point)正常完成后执行的通知
抛出异常后通知(After throwing advice) 在方法抛出异常退出时执行的通知
后通知(After(finally) advice) 当某个连接点退出的时候执行的通知(无论是正常返回还是异常退出)
环绕通知(Around advice) 包围一个连接点(join point)的通知

导入需要的包:aspectjweaver.jar、aopalliance-1.0.jar

(一)Before Advice

例子:

新建两个类:

package com.aop.schema;
/**
*
* 切面类
*
*/
public class MyAspect { public void before(){
System.out.println("MyAspect.before");
}
}
package com.aop.schema;
/**
*
* 业务类
*
*/
public class ApsectBiz { public void biz(){
System.out.println("ApsectBiz.biz");
}
}

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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <bean id="myAspect" class="com.aop.schema.MyAspect"></bean> <bean id="apsectBiz" class="com.aop.schema.ApsectBiz"></bean> <aop:config>
<aop:aspect id="myAspectAOP" ref="myAspect">
<aop:pointcut id="myPointcut" expression="execution(* com.aop.schema.ApsectBiz.*(..))" />
<aop:before method="before" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config> </beans>

单元测试:

package com.aop.schema;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class UnitTest { @Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-aop.xml");
ApsectBiz biz = (ApsectBiz)context.getBean("apsectBiz");
biz.biz();
}
}

结果:

七月 09, 2015 10:30:24 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Thu Jul 09 22:30:24 CST 2015]; root of context hierarchy
七月 09, 2015 10:30:24 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
MyAspect.before
ApsectBiz.biz

PS:ApsectBiz.biz是业务方法,在它之前,执行了前置通知MyAspect.before,符合想要的结果

(二)After returning advice

例子:

修改一下切面类MyAspect(添加afterreturning方法):

package com.aop.schema;
/**
*
* 切面类
*
*/
public class MyAspect { public void before(){
System.out.println("MyAspect.before");
} public void afterreturning(){
System.out.println("MyAspect.afterreturning");
}
}

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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <bean id="myAspect" class="com.aop.schema.MyAspect"></bean> <bean id="apsectBiz" class="com.aop.schema.ApsectBiz"></bean> <aop:config>
<aop:aspect id="myAspectAOP" ref="myAspect">
<aop:pointcut id="myPointcut" expression="execution(* com.aop.schema.ApsectBiz.*(..))" />
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after-returning method="afterreturning" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config> </beans>

单元测试同上:

结果:

七月 09, 2015 10:38:41 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Thu Jul 09 22:38:41 CST 2015]; root of context hierarchy
七月 09, 2015 10:38:41 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
MyAspect.before
ApsectBiz.biz
MyAspect.afterreturning

(三)After throwing advice

说明:使用throwing属性来指定可被传递的异常的参数名称

例子:

修改一下切面类MyAspect(添加afterthrowing方法):

package com.aop.schema;
/**
*
* 切面类
*
*/
public class MyAspect { public void before(){
System.out.println("MyAspect.before");
} public void afterreturning(){
System.out.println("MyAspect.afterreturning");
} public void afterthrowing(){
System.out.println("MyAspect.afterthrowing");
}
}

修改业务类ApsectBiz(抛出一个异常):

package com.aop.schema;

/**
*
* 业务类
*
*/
public class ApsectBiz { public void biz(){
System.out.println("ApsectBiz.biz");
throw new RuntimeException(); //故意抛出异常
}
}

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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <bean id="myAspect" class="com.aop.schema.MyAspect"></bean> <bean id="apsectBiz" class="com.aop.schema.ApsectBiz"></bean> <aop:config>
<aop:aspect id="myAspectAOP" ref="myAspect">
<aop:pointcut id="myPointcut" expression="execution(* com.aop.schema.ApsectBiz.*(..))" />
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after-returning method="afterreturning" pointcut-ref="myPointcut"/>
<aop:after-throwing method="afterthrowing" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config> </beans>

单元测试同上:

测试结果:

七月 09, 2015 10:47:46 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Thu Jul 09 22:47:46 CST 2015]; root of context hierarchy
七月 09, 2015 10:47:46 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
MyAspect.before
ApsectBiz.biz
MyAspect.afterthrowing

PS:有没有发现有什么问题? MyAspect.afterreturning没有了,biz()中抛出异常,biz()方法没有正常返回,所以MyAspect.afterreturning没有了。

(四)After(finally) advice

修改一下切面类MyAspect(添加after方法):

package com.aop.schema;
/**
*
* 切面类
*
*/
public class MyAspect { public void before(){
System.out.println("MyAspect.before");
} public void afterreturning(){
System.out.println("MyAspect.afterreturning");
} public void afterthrowing(){
System.out.println("MyAspect.afterthrowing");
} public void after(){
System.out.println("MyAspect.after");
}
}

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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <bean id="myAspect" class="com.aop.schema.MyAspect"></bean> <bean id="apsectBiz" class="com.aop.schema.ApsectBiz"></bean> <aop:config>
<aop:aspect id="myAspectAOP" ref="myAspect">
<aop:pointcut id="myPointcut" expression="execution(* com.aop.schema.ApsectBiz.*(..))" />
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after-returning method="afterreturning" pointcut-ref="myPointcut"/>
<aop:after-throwing method="afterthrowing" pointcut-ref="myPointcut"/>
<aop:after method="after" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config> </beans>

单元测试同上:

结果:

七月 09, 2015 10:56:10 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Thu Jul 09 22:56:10 CST 2015]; root of context hierarchy
七月 09, 2015 10:56:10 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
MyAspect.before
ApsectBiz.biz
MyAspect.afterthrowing
MyAspect.after

(五)Around advice

注意:通知方法的第一个参数必ProceedingJoinPoint类型

例子:

修改一下切面类MyAspect(添加around方法):

package com.aop.schema;

import org.aspectj.lang.ProceedingJoinPoint;

/**
*
* 切面类
*
*/
public class MyAspect { public void before(){
System.out.println("MyAspect.before");
} public void afterreturning(){
System.out.println("MyAspect.afterreturning");
} public void afterthrowing(){
System.out.println("MyAspect.afterthrowing");
} public void after(){
System.out.println("MyAspect.after");
} public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("MyAspect.around_1");
Object obj=pjp.proceed();
System.out.println("MyAspect.around_2");
}
}

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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <bean id="myAspect" class="com.aop.schema.MyAspect"></bean> <bean id="apsectBiz" class="com.aop.schema.ApsectBiz"></bean> <aop:config>
<aop:aspect id="myAspectAOP" ref="myAspect">
<aop:pointcut id="myPointcut" expression="execution(* com.aop.schema.ApsectBiz.*(..))" />
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after-returning method="afterreturning" pointcut-ref="myPointcut"/>
<aop:after-throwing method="afterthrowing" pointcut-ref="myPointcut"/>
<aop:after method="after" pointcut-ref="myPointcut"/>
<aop:around method="around" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config> </beans>

单元测试同上:

结果:

七月 09, 2015 11:15:20 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Thu Jul 09 23:15:20 CST 2015]; root of context hierarchy
七月 09, 2015 11:15:20 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
MyAspect.before
MyAspect.around_1
ApsectBiz.biz
java.lang.RuntimeException
at com.aop.schema.ApsectBiz.biz(ApsectBiz.java:11)
at com.aop.schema.ApsectBiz$$FastClassBySpringCGLIB$$ae10254d.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
at com.aop.schema.MyAspect.around(MyAspect.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:43)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.aop.schema.ApsectBiz$$EnhancerBySpringCGLIB$$1fbf7bae.biz(<generated>)
at com.aop.schema.UnitTest.test(UnitTest.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
MyAspect.after
MyAspect.afterreturning

PS:有异常,仔细看,原来是around(ProceedingJoinPoint pjp)的try catch捕捉到了biz()抛出的异常,现在把异常注释掉(try catch里面怎么处理异常?这里要看具体的业务需要,这里先注释掉)

package com.aop.schema;
/**
*
* 业务类
*
*/
public class ApsectBiz { public void biz(){
System.out.println("ApsectBiz.biz");
//throw new RuntimeException(); //故意抛出异常
}
}

测试结果:

七月 09, 2015 11:18:17 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Thu Jul 09 23:18:17 CST 2015]; root of context hierarchy
七月 09, 2015 11:18:17 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
MyAspect.before
MyAspect.around_1
ApsectBiz.biz
MyAspect.around_2
MyAspect.after
MyAspect.afterreturning

Spring学习(21)--- AOP之Advice应用(上)的更多相关文章

  1. Spring学习之AOP的实现方式

    Spring学习之AOP的三种实现方式 一.介绍AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能 ...

  2. spring学习(二) ———— AOP之AspectJ框架的使用

    前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...

  3. Spring学习之AOP总结帖

    AOP(面向方面编程),也可称为面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP). 在进行 OOP 开发时,都是基于对组件(比如类)进行开发,然后对组件进行组 ...

  4. Spring学习之AOP

    Spring-AOP(Aspect-orented programming) 在业务流程中插入与业务无关的逻辑,这样的逻辑称为Cross-cutting concerns,将Crossing-cutt ...

  5. Spring学习之Aop的各种增强方法

    AspectJ允许使用注解用于定义切面.切入点和增强处理,而Spring框架则可以识别并根据这些注解来生成AOP代理.Spring只是使用了和AspectJ 5一样的注解,但并没有使用AspectJ的 ...

  6. Spring学习之Aop的基本概念

    转自:http://my.oschina.net/itblog/blog/209067 AOP的基本概念 AOP从运行的角度考虑程序的流程,提取业务处理过程的切面.AOP面向的是程序运行中的各个步骤, ...

  7. Spring学习之AOP与事务

      一.概述 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续, ...

  8. spring学习笔记-AOP

    1.aop:aspect oriented programming 面向切面编程 2.aop在spring中的作用:   提供声明式服务(声明式事务) 允许用户实现自定义切面 3.aop:在不改变原有 ...

  9. Spring 学习二-----AOP的原理与简单实践

    一.Spring  AOP的原理 AOP全名Aspect-Oriented Programming,中文直译为面向切面(方面)编程.何为切面,就比如说我们系统中的权限管理,日志,事务等我们都可以将其看 ...

  10. Spring学习之==>AOP

    一.概述 AOP(Aspect Oriented Programming)称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等,Struts2的拦截器设计就是基于A ...

随机推荐

  1. CodeVS1344 线型网络

    题目描述 Description 有 N ( <=20 ) 台 PC 放在机房内,现在要求由你选定一台 PC,用共 N-1 条网线从这台机器开始一台接一台地依次连接他们,最后接到哪个以及连接的顺 ...

  2. 调用startActivityForResult后,onActivityResult为什么立刻响应

    现象      今天在编写代码的时候,涉及到两个Activity通过Intent来传值的问题.具体描述为:activity A调用startActivityForResult()函数启动Activit ...

  3. [UWP]了解模板化控件(9):UI指南

    1. 使用TemplateSettings统一外观 TemplateSettings提供一组只读属性,用于在新建ControlTemplate时使用这些约定的属性. 譬如,修改HeaderedCont ...

  4. OC中的单例

    概念 单例模式的意图是类的对象称为系统中唯一的实例,提供一个访问点,供客户类共享资源 什么情况下使用单例 )类只能由一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法 )这个唯一的实例 ...

  5. java集合系列

    工作以来,一直对java集合理解的不够全面,不够深入,就是常用的ArrayList/HashMap/Set/List,有时候会用一下LinkedList.一时兴起,可能对TreeSet,HashSet ...

  6. vue.js 初体验— Chrome 插件开发实录

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:陈纬杰 背景 对于经常和动画开发打交道的开发者对于Animate.css这个动画库不会陌生,它把一些常见 ...

  7. jquery源码 DOM加载

    jQuery版本:2.0.3 DOM加载有关的扩展 isReady:DOM是否加载完(内部使用) readyWait:等待多少文件的计数器(内部使用) holdReady():推迟DOM触发 read ...

  8. Python装饰器实现几类验证功能做法(续)

    :昨天聊了一下构造.今天试了一下.感觉昨天聊的还是不够细化.今天结合代码实现,加以一点补充. 首先观察下面这个例子 from functools import wrapsdef decorator(f ...

  9. Ultimus BPM 制药与医疗行业应用解决方案

    Ultimus BPM 制药与医疗行业应用解决方案 行业应用需求 制药与医疗行业客户特点有企业总资产高.员工规模大,销售网络往往遍及全国,乃至全球市场:拥有复杂的制药生产或医疗服务组织机构,并均有严格 ...

  10. 发布自己第一个npm 组件包(基于Vue的文字跑马灯组件)

    一.前言 总结下最近工作上在移动端实现的一个跑马灯效果,最终效果如下: 印象中好像HTML标签的'marquee'的直接可以实现这个效果,不过 HTML标准中已经废弃了'marquee'标签 既然HT ...