发表于: 2018-02-07 23:20:26

1 739


完成

1.统计访问DB时间,Controller处理时间,这个需要用到SpringAOP知识

什么是AOP——Aspect Orient Programming

面向切面,是一种编程思想,OOP的延续。将系统中非核心的业务提取出来,进行单独处理。比如事务、日志和安全等。这个简单来说就是可以在一段程序之前或者之后做一些事。

为什么用AOP:你一开始只想写个功能A,B,C,后来,客户提出,你要进行登录验证,于是你在三段代码里加上了这个功能,后来,客户又说你要做日志记录,你又加上了这个功能。

  但是需求是永远会变的,你的ABC随着时间的进行,可能多出了越来越多的无关的代码或者函数调用,这样显然不好。如果可以,你写一段代码,系统可以“自动”再需要的地方调用它——那么AOP就是为了满足这样的需求,常常用来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等等

       Spring 的AOP和IOC都是为了解决系统代码耦合度过高的问题。使代码重用度高、易于维护。

不过AOP和IOC并不是spring中特有的,只是spring把他们应用的更灵活方便

AOP核心概念
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)

在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段


这里有很通俗的解释(https://segmentfault.com/a/1190000007469968

用注解式跑了一个demo(其实也可以用xml式跑)

AnnotationTest类

package com.wlj.aop2;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component("annotationTest")
@Aspect
public class AnnotationTest {
//定义切点
   @Pointcut("execution(* *.saying(..))")
public void sayings() {
}
   @Before("sayings()")
public void sayHello() {
System.out.println("注解类型前置通知");
   }

//后置通知
   @After("sayings()")
public void sayGoodbey() {
System.out.println("注解类型后置通知");
   }

//环绕通知。注意要有ProceedingJoinPoint参数传入。
   @Around("sayings()")
public void sayAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("注解类型环绕通知..环绕前");
       pjp.proceed();//执行方法
       System.out.println("注解类型环绕通知..环绕后");
   }
}

BraveKnight类

package com.wlj.aop2;

import org.springframework.stereotype.Component;

@Component("knight")
public class BraveKnight {

public void saying(){
System.out.println("我是骑士..(切点方法)");
   
}

spring配置文件里加上

<context:component-scan base-package="com.wlj.aop2"/>
<!-- 开启aop注解方式,此步骤s不能少,这样java类中的aop注解才会生效 -->
<aop:aspectj-autoproxy/>
<!--注意:我们不仅仅要引入Aop的名称空间,还要在xsi:schemaLocation中加入aopxsd文件 ,缺一不可-->
<!--否则会报错:通配符的匹配很全面, 但无法找到元素 'aop:aspectj-autoproxy' 的声明。-->

测试类

@Test
public void aop2() {
ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml");
   BraveKnight br = (BraveKnight) ac.getBean("knight");
   br.saying();
}

结果(截图发不出来)

  注解类型环绕通知..环绕前

注解类型前置通知

我是骑士..(切点方法)

注解类型环绕通知..环绕后

注解类型后置通知


接下来的是任务要求的demo(这里参考了于师兄的日报,自己弄了很久没有实现)

package com.wlj.aop5;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;

import java.text.SimpleDateFormat;
import java.util.Date;

public class LogAdvice {

private static Logger loggerAdvice = Logger.getLogger(LogAdvice.class);

   public Object around(ProceedingJoinPoint pip) throws Throwable {
//获取组件类名
       String className = pip.getTarget().getClass().getName();
       //获取调用方法名
       String method = pip.getSignature().getName();
       //取得数据库连接前时间
       long begin = System.currentTimeMillis();
       //当前系统时间
       String date = new SimpleDateFormat("yyyy-MM-dd:mm:ss").format(new Date());
       Object obj = pip.proceed();

       //取得数据库连接后时间
       long end = System.currentTimeMillis();
       //数据库响应时间
       int sqlTime = (int) (end - begin);
       String msg = date + ",执行了" + className + "." + method + "()";

       loggerAdvice.warn(msg + "\t数据库响应时间: " + sqlTime);
       return obj;

   }
}

spring配置文件加入

<bean id="LogAdvice" class="com.wlj.aop5.LogAdvice"/>

<aop:config>
   <aop:pointcut id="pct" expression="execution(* com.wlj.service.*Impl.*(..))"/>
   <aop:aspect id="myAspect" ref="LogAdvice">
       <aop:around method="around" pointcut-ref="pct"/>
   </aop:aspect>

</aop:config>

结果


问题

aop还要加深理解


收获

学了aop,面向切面编程


计划

把剩下的脚本写好,学自动部署







返回列表 返回列表
评论

    分享到