理解AOP概念
aop是什么:
简介1.AOP(Aspect Oriented Programming)是 spring框架的一个重要的特征,AOP把一个业务流程分成几部分,例如:权限检查,业务处理,记录日志,每个部分单独处理,然后把它们组装成完整的业务流程。每个部分被称为切面儿(Aspect)或者关注点。
aop中一些重要概念:
包括切面,连接点(Joinpoint),通知(Advice),切入点(Pointcut),引用(Introduction),这些概念不是spring定义的。
系统学习aop基础
1.初次接触aop,对aop的理解是,一个项目中通用功能的实现需要使用aop,比如权限管理,记录日志,是一个面向切面编程。
2.现在开始系统学习aop的基础,较好的方式去结合spring aop的官方文档,继而再在项目中得以实践。
- 使用aop钱需要导入的jar包以及配置
- jar包
- aspectjweaver
- aspectjtools
- aspectjjrt 版本统一 1.8.9,导入1.8.8注解不生效 可能和jdk有关
- 注解以及配置
- jar包
用于支持注解版的AOP @Aspect: < aop:aspectj-autoproxy/>
1.问题1:aop编程是如何切入到程序中可以debug跟踪。
Spring利用动态代理API(反射API的部分)将切面程序织入现有程序中。
2.AOP的优点以及用途
优点:在不改变原有的程序的情况下插入(扩展)出功能,一般都是切向(横截面)功能。
用途:切向(横截面)功能扩展:日志,功能审计,性能追踪等。
3.通知(Advice)
常用的 通知
通知(Advice):是切面程序相对以被拦截的方法调用位置
//第一种方式 aop以捕获异常的方式处理我们的程序
try{
//1.@Before()
//2.@AfterReturning() //有异常的时候不执行
}catch(){
//3.@AfterThrowing() //没有异常的时候不执行
}finally{
//4.@After()
}
//第二种方式 @Around 环绕的方式
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class AroundExample {
@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint joinPoint) throws Throwable {
// start stopwatch(启动秒表)
//调用业务方法
Signature s = joinPoin.getSignature();
System.out.println(s);//输出方法签名
Object retVal = joinPoint.proceed();
// stop stopwatch(终止秒表)
return retVal;//业务方法返回值
}
}
4.常用切入点(Pointcut)
切入点(Pointcut):是将AOP组件织入到那个类的哪个方法
提示:找到方法以后,在方法的前后位置由“通知”决定。
- bean组件 如bean(* service)
- execution
- within
上述的切入点指定的规则参考可以参考spring framework (AOP)开发参考手册 1.中文可以参考(2.*版本)http://shouce.jb51.net/spring/
AOP性能审计实例
需要对线程以及双缓冲队列(BlockingQueue)有清楚的了解
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 记录每个业务方法的执行时间
* 保存到文件中
*
*/
@Component
@Aspect
public class TimeLogerAspect {
//用阻塞(缓冲)队列
private BlockingQueue<String> queue = new LinkedBlockingQueue<String>(500);//blockingQueue是接口,linked..是它的实现类
private String filename;
@Value("#{config.filename}")
public void setFilename(String filename) {
this.filename = filename;
file = new File(filename);
}
private File file ;
private Thread writer;
public TimeLogerAspect(){
writer = new Thread(){
public void run() {
while(true){
try{
if(queue.isEmpty()){
Thread.sleep(500);
continue;
}
//发现队列中有数据
PrintWriter out = new PrintWriter(new FileOutputStream(file,true));//现在是覆盖
while(! queue.isEmpty()){
String str = queue.poll();
out.println(str);
}
out.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
};
writer.start();
}
@Around("execution(* cn.tedu.note.service.*Service.*(..))")
public Object proc(ProceedingJoinPoint joinPoint) throws Throwable{
long t1 = System.nanoTime();
Object val = joinPoint.proceed();
long t2 = System.nanoTime();
Signature s = joinPoint.getSignature();
//System.out.println(System.currentTimeMillis()+":"+s+":" +(t2-t1));
String str = System.currentTimeMillis() + ":" + s +":"+(t2-t1);
queue.offer(str);//数据的生产
return val;
}
}
//注意需要在resource下创建一properties文件;以及配置此文件,beande的id为config。