jQuery EasyUI的使用入门
啥是AOP?为啥要有AOP呢?OOP用着不香吗?
OOP是面向对象编程,AOP是面向切面编程。OOP全称是Object Oriented Programming,AOP全称是Aspect Oriented Programming,aspect就是面/方面/切面的意思。
假如要在一些核心业务模块添加一些外围业务的操作,如记录日志、权限判断等,这种情况下用AOP最合适了。第一,不会污染核心业务代码,这些代码没有和核心业务代码放在一起,改动时不用改动核心业务模块。第二,这些代码是可插拔的,哪些核心业务模块想用或者不想用,就直接配置或者取消配置即可。AOP的目的是解决外围业务代码与核心业务代码分离的问题,它不会替代OOP。OOP是把编码问题模块化,而AOP是把涉及多个模块的某一类问题统一管理。
AOP的实现技术有多种,其中与java无缝对接的是AspectJ。J就是java的意思。
AspectJ是Eclipse基金会的一个项目。官网地址是https://www.eclipse.org/aspectj/
github地址是https://github.com/eclipse/org.aspectj
AspectJ AOP
要编写AspecJ文件,关键字是aspect,文件后缀是.aj。开发AspectJ项目,IDE需要安装AspectJ Support插件,代码需要引入aspectj相关jar,从maven仓库直接搜即可,且编译器要用特殊的编译器,不能用javac了,javac不认识aj文件,要用ajc(是aspectj compiler的简称)。ajc编译器用于编译.aj文件,它也可以编译java文件。

新建时,选择Aspect,而不是Java Class。

下面以在某个方法执行完毕时打印日志的这个需求为例:
public class HelloWorld {
public void sayHello() {
System.out.println("hello world !");
}
public static void main(String args[]) {
HelloWorld helloWord = new HelloWorld();
helloWord.sayHello();
}
}
有一个HelloWorld类,想在sayHello()方法执行完毕后打印一条日志。
则我们可以新建切面类,在其中用pointcut关键字定义切点,用after、before等关键字定义后置通知、前置通知。如下:
public aspect MyAspectJDemo {
/*
切点
*/
pointcut recordLog():execution(* HelloWorld.sayHello(..));
/*
前置通知
*/
before():recordLog(){
System.out.println("sayHello方法执行前记录日志");
}
/*
后置通知
*/
after():recordLog(){
System.out.println("sayHello方法执行后记录日志");
}
}
recordLog是切点名,用pointcut关键字修饰。execution是固定的,括号里面是采用这个关注点的方法,*表示任意返回类型,HelloWorld.sayHello表示Helloworld类的sayHello方法,sayHello后面括号两个点表示任意入参。
除了before代表的前置通知、after代表的后置通知外,还有环绕通知,用around关键字。环绕通知比较特殊,一定要有返回值,否则在编译时会报语法错误,insert "return type" to complete around advice declaration。并且必须调用proceed()方法,否则不会到核心模块的代码中去,这里就好像filter的doFilter操作,不过proceed()是有返回值的,返回值就是包裹的方法的返回值,如果包裹的方法返回值是void,则proceed()方法返回null。
public aspect MyAspectJDemo {
pointcut recordTimeCost():call(* HelloWorld.sayHello(..));
Object around():recordTimeCost(){
System.out.println("计时开始");
long begin = System.currentTimeMillis();
Object o = proceed();
System.out.println("cost " + (System.currentTimeMillis() - begin) + "ms");
return o;
}
}
用aspectj关键字定义的类叫做切面,如上面的MyAspectJDemo,在切面中使用pointcut关键字定义切点,使用before、after、around关键字定义前置通知、后置通知、环绕通知。所谓的切点就是那些需要应用切面的方法,也称为目标方法,如上面的sayHello方法。通知,英文是advice,就是那些需要在目标方法或前或后或前后执行的方法,分为前置通知,在目标方法执行前执行,后置通知,在目标方法执行后执行,环绕通知,在目标方法执行前和执行后执行。
实际上,AspectJ从1.5开始(06年左右),就引入了@Aspect、@Pointcut、@Before、@After、@Around等注解,使我们可以用注解开发,大大提高了开发效率。这些注解都在aspectjweaver.jar中。
上例如果用注解风格开发,则可以改造成:
@Aspect
public class MyAspectJDemo { @Pointcut(value = "execution(* HelloWorld.sayHello(..))")
public void xx() {
} @After(value = "xx()")
public void recordLog() {
System.out.println("sayHello方法执行后记录日志");
} }
把aj文件改成java文件(源文件后缀名可以不改,但是要用class关键字替代aspect关键字),用@Aspect标注切面类,用@Pointcut注解替代pointcut关键字,@Pointcut的value属性值中不能再用call引导目标方法了,必须用execution。用@After注解替代after关键字。注意,此时还是必须用ajc编译器,用javac编译器不行。
用注解的话,还可进一步优化,省略@Pointcut注解及其标注的方法,把@Pointcut注解的value属性值放到@Before、@AfterThrowing、@Around等的value属性中。示例:
@Aspect
public class MyAspectJDemo { @After(value = "execution(* HelloWorld.sayHello(..))")
public void recordTimeCost() {
System.out.println("计时开始ingsfsdf");
} @AfterThrowing(value = "execution(* HelloWorld.sayHello(..))", throwing = "e")
public void handleException(Exception e) {
e.printStackTrace();
} @Around(value = "execution(* HelloWorld.sayHello(..))")
public Object aroundHandle(ProceedingJoinPoint joinPoint) {
System.out.println("环绕通知");
try {
return joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("环绕通知后");
return ImmutableMap.of("result", -1);
} }
这里额外指出一下,使用@Around注解时,标注的方法的参数必须是ProceedingJoinPoint类型。通过这个ProceedingJoinPoint实例的getTarget(),我们可得到当前目标方法所在类的class实例,进而得到类名。通过这个ProceedingJoinPoint实例的getSignature()方法得到Signature实例,调用其getName()方法可以得到方法名。这样就解决了上面的第1个疑问。再多说一点,在其他通知注解,如@Before、@AfterThrowing等标注的方法中,我们可以给方法一个JoinPoint类型的入参,在方法内部就可以调用这个JoinPoint实例获取当前目标方法的类名、方法名了。ProceedingJoinPoint是JoinPoint的子接口。
第二个疑问其实就是匹配表达式问题,到用的时候直接google就好了。
到现在还有一个概念没有讲,那就是织入。所谓织入,就是指把切面应用到目标方法的过程,英文是weaving。织入可以分为静态织入和动态织入。
AspecJ采用的是编译期织入,用acj编译器把切面编译成class字节码后,在目标类编译时织入,是静态织入的一种。静态织入除了编译期织入,还有链接期织入,不在此详述。
动态织入指的是在运行时动态地将增强的代码织入到目标方法中,是通过动态代理实现的。Spring AOP采用的就是动态织入。
Spring AOP
考虑到AspectJ对ajc编译器的强依赖性,在spring项目中最好使用Spring AOP,不仅解除了对ajc编译器的依赖,还能够与Spring IOC很好的结合。
从Spring 2.0开始,Spring就支持AspectJ的注解。注意,用Spring AOP时,还必须引入aspectjweaver.jar,用这个jar包中的注解类呢。
Spring AOP的代码在AspectJ AOP注解风格写法的基础上稍微改下就可以了。
1、把切面类由aspect MyAspectJDemo改成class MyAspectJDemo,即不再创建aspect文件,而是创建java文件。同样用@Aspect注解标注。注意没有@AspectJ注解。
2、用@EnableAspectJAutoProxy标注上面切面类,表示启用AspectJ的各种注解,@EnableAspectJAutoProxy注解是Spring提供的。如果不用@EnableAspectJAutoProxy注解,则还可以在spring的配置文件中添加<aop:aspectj-autoproxy proxy-target-class="true"/>,效果是一样的。注意,如果是spring mvc的web项目,则<aop:aspectj-autoproxy/>必须放在spring mvc对应的配置文件中,放在spring的applicationContext文件中,aop不生效。
为啥有时候用@EnableAspectJAutoProxy注解不行,用<aop:aspectj-autoproxy/>可以呢?
3、用@Component标注切面类。
就这样,切面类内部的切点和通知不用做任何改动。
示例:
@Aspect
@EnableAspectJAutoProxy
@Component
public class MySpringAopAspect { @Pointcut("execution(* HelloWorld.sayHello(..))")
public void recordLog() {
} @Before(value = "recordLog()")
public void xxx() {
System.out.println("前置通知....");
} }
此时,我们可以尝试写一个处理全局异常的一个切面类ExceptionHandlerAspect,如下:
@Aspect
@EnableAspectJAutoProxy
@Component
public class ExceptionHandlerAspect { @Around(value = "execution(* com.kou.controller.*Controller.*(..))")
@ResponseBody
public Object handleException(ProceedingJoinPoint joinPoint) {
try {
return joinPoint.proceed();
} catch (Throwable t) {
t.printStackTrace();
}
return ImmutableMap.of("result", -1);
} }
在切面中,用了@Around注解,而没有用@AfterThrowing注解,这是因为@AfterThrowing标注的方法不能有返回值,不能返回通用错误码,且也不能把Throwable实例catch住。而在@Around标注的方法中,可以对joinPoint.proceed()进行try catch,如果proceed()方法不抛异常,则正常返回,如果抛了异常,则返回通用错误码。
spring提供了几个额外的注解,用来处理全局异常,@ExceptionHandler、@ControllerAdvice、@RestControllerAdvice。我们用这些注解也一样可以处理全局异常,
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Object exceptionHandler(Exception e) {
e.printStackTrace();
return ImmutableMap.of("result", -1);
}
}
@RestControllerAdvice注解是@ControllerAdvice注解和@ResponseBody的组合体。
再研究下Advice后缀的多个注解,如。是干啥的呢
Spring AOP是如何用动态代理的呢?
Spring所有代理类(AopProxy)都是通过ProxyCreatorSupport的createAopProxy()实例方法创建的。
jQuery EasyUI的使用入门的更多相关文章
- 第一百九十一节,jQuery EasyUI 入门
jQuery EasyUI 入门 学习要点: 1.什么是 jQuery EasyUI 2.学习 jQuery EasyUI 的条件 3.jQuery EasyUI 的功能和优势 4.其他的 UI 插件 ...
- 第 1 章 jQuery EasyUI 入门
学习要点: 1.什么是 jQuery EasyUI 2.学习 jQuery EasyUI 的条件 3.jQuery EasyUI 的功能和优势 4.其他的 UI 插件 5.是否兼容低版本 IE 6.下 ...
- jQuery EasyUI 入门简介
对于前端开发者来说,在开发过程中应用“框架”这一工具,可以极大的缩短开发时间,提高开发效率.今天我们就开介绍一款常用的框架——jQuery EasyUI. 那什么是jQuery EasyUI呢? jQ ...
- jQuery EasyUI视频教程合集
下载地址:http://www.fu83.cn/thread-269-1-1.html 教程内容: 尚学堂科技_jqueryeasyui视频教程_白贺翔 李炎恢jQuery EasyUI视频教程全集 ...
- Jquery EasyUI的添加,修改,删除,查询等基本操作介绍
http://www.jb51.net/article/42016.htm 初识Jquery EasyUI看了一些博主用其开发出来的项目,页面很炫,感觉功能挺强大,效果也挺不错,最近一直想系统学习一套 ...
- JQuery EasyUI框架学习
前言 新项目的开发前端技术打算採用EasyUI框架(基于EasyUI较为丰富的UI组件库),项目组长将前端EasyUI这块的任务分配给了我.在进行开发之前,须要我这菜鸟对EasyUI框架进行一些基础的 ...
- JQuery EasyUI学习框架
前言 前端技术,新项目的开发拟使用EasyUI框架(基于EasyUI丰富UI组件库),项目负责人的提示EasyUI分配给我这个任务.发展前,我需要这对于一个新手EasyUI框架学习一些基本的入门.记录 ...
- jQuery EasyUI学习资源汇总
jQuery EasyUI学习资源汇总 EasyUi – 1.入门 EasyUi – 2.布局Layout + 3.登录界面 EasyUi – 4.datwagrid 学习Jquery EasyUI的 ...
- jQuery EasyUI一个基于 jQuery 的框架(创建网页所需的一切)
jQuery EasyUI学习网址:http://www.runoob.com/jeasyui/jqueryeasyui-tutorial.html jQuery MiniUI学习网址:http:// ...
随机推荐
- while循环的基本用法
while是常用的循环结构之一 1.格式: while(条件){ } 2.基本知识点 1)puts(“字符串”).换行输出一个字符串 2)死循环.. while(1){ } 代码如下:
- 在Linux Mint13下编译安装mono运行时
最近一直想体验下mono在web开发上到底进展到什么程度,挑战一下它对web开发的极限.因为asp.net mvc本身依赖windows平台的东西不太多,所以这些assembly移植到mono/lin ...
- Ext JS4百强应用: 用grid.plugin.CellEditing做高级查询 --第10强
Ext JS4,用grid.plugin.CellEditing做高级查询: 写了90%,界面出来了,小兴奋就贴出来,还有细节要调整,基本能用. 代码: Ext.define('chenghao.ad ...
- angularjs控制器之间通信,事件通知服务
service要记住一点就是所有的services都是singleton(单例)的,service更多的是做一些业务逻辑,数据交互.当然,利用单例这特点也可以用来做不同控制器间的通信.控制器间的通信也 ...
- java String源码学习
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ...
- DNS解析详细过程
英文:domain name system. 中文:域名系统. 解析过程: 第一次请求站点(例:http://www.baidu.com),先在当前浏览器路径下寻找有没有缓存对应的解析结果,如果有的话 ...
- nginx整合tomcat集群并做session共享----测试案例
最近出于好奇心,研究了一下tomcat集群配置,并整合nginx,实现负载均衡,session共享,写篇记录,防止遗忘.---------菜鸡的自我修炼. 说明:博主采用一个web项目同时部署到两台t ...
- .NET基础——循环、枚举
1. 循环结构 3种循环语句:while.do-while.for 面对循环我们应当注意: 1. 循环在做什么?(重复做的事情——也就是循环体的内容) 2. 循环的终止条件是什么?(循环条件) 3种循 ...
- 手机无须ROOT不用修改hosts即可在本地测试安卓、苹果APP和H5应用
开发手机APP和 H5 应用经常需要在本地和线上环境分开测试,一般想到的操作都是修改hosts,我也一直这么干的,但手机上修改hosts是需要 ROOT权限的,这样太过麻烦,还有变砖头的风险,而且有些 ...
- Mybatis学习笔记(二) 之实现数据库的增删改查
开发环境搭建 mybatis 的开发环境搭建,选择: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包.这些软件工具均可以到各自的官方网站上下载 ...