spring AOP

Spring AOP

AOP:面向切面编程(aspect oriented programming)

将系统中共同的业务处理从传统的业务处理中抽离出来,

单独封装,然后以配置的形式进行关联

可以在不修改原有逻辑代码的情况下,给系统追加功能

 

AOP的典型应用

追加事务控制

异常日志记录

案例:

要求:在每个controller方法执行前输出一个打桩信息

封装一个组件

通过配置将封装的组件追加到controller方法上

 

切面:实现追加功能的一段代码

配置文件:

<bean id="loggerBean" class="cn.tedu.cloudnote.aspect.LoggerBean"></bean>

<aop:config>

<!-- 通过ref关联组件类 -->

<aop:aspect ref="loggerBean">

<!-- 通过method指定处理方法 -->

<!-- pointcut:切入点,作用到controller -->

<aop:before method="logController"  pointcut="within(cn.tedu.cloudnote.controller..*)"/>

</aop:aspect>

  </aop:config>

导入aspectjweaver.jar

 

AOP相关概念

OOP:类,对象,封装,继承,多态

AOP:

切面:aspect

封装了共同处理的组件,并且能够切入到其他组件的方法上

切入点:pointcut

用于指定目标组件的方法

切入点的有关表达式

方法限定表达式

可以给某个组件中部分方法追加共同功能

execution(修饰符 返回类型 方法名称(参数)异常抛出)

execution(* add*(..))//匹配到add开头的所有方法

execution (* cn.tedu.Userservice.*(..))//匹配Userservice包的所有方法

execution (* cn.tedu.service..*(..))//匹配service包及其子包的所有方法

<aop:before method="logController" 

pointcut="execution(*cn.tedu.cloudnote.controller..*(..))">

 

类型限定表达式(常用)

可以给某个组件的所有方法追加功能

Within(类型)

//匹配UserService组件下所有的方法,不指定具体的方法

Within(cn.tedu.cloudnote.service.UserService)

//匹配某个包下所有类的所有方法

Within(cu.tedu.cloudnote.service.*)

//匹配某个包及其子包下所有类的所有方法

Within(cu.tedu.cloudnote.service..*)

 

Bean名称限定表达式

可以给某个组件中所有的方法追加功能

bean(id名)

//匹配id为UserService的组件中的所有方法

bean(userService)

//匹配以Service结尾的所有组件的所有方法

bean(*Service)

实例:

<bean id="loggerBean" class="cn.tedu.cloudnote.aspect.LoggerBean"></bean>

<aop:config>

<!-- 通过ref关联组件类 -->

<aop:aspect ref="loggerBean">

<!-- 通过method指定处理方法 -->

<!-- pointcut:切入点,作用到controller -->

<!-- 类型限定表达式(常用) -->

<!-- <aop:before method="logController" pointcut="within(cn.tedu.cloudnote.controller..*)"/> -->

<!-- 方法限定表达式 -->

<!-- <aop:before method="logController" pointcut="execution(* cn.tedu.cloudnote.controller..*(..))"/> -->

<!-- Bean名称限定表达式 -->

<aop:before method="logController" pointcut="bean(*Service)"/>

</aop:aspect>

</aop:config>

 

通知:

用于指定切入的时机

Spring提供了5种通知类型

try{

前置通知:<aop:before>

//执行目标方法

后置通知:<aop:after-returning>

}catch{

异常通知:<aop:after-throwing>

}finall{

最终通知:<aop:after>

}

环绕通知:@around=前置通知+后置通知

 

切面:住家啥功能?单独封装的代码

切入点:切谁?所有Controller

通知:什么时候切入?前置/后置/环绕

 

<!-- spring 的事务管理 -->

<!-- 定义事务管理的bean -->

<bean id="txManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dbcp"></property>

</bean>

<!--开启transaction标记,将标记作用在具体方法上 -->

<tx:annotation-driven transaction-manager="txManger"/>

 

 动态代理

AOP原理:

使用动态代理技术

可以创建一个新的类型,重写目标接口或目标类的方法

在重写方法中,追加了要切入的功能代码和方法代码

 

Spring有两种动态技术

基于目标接口

基于目标类

 

Public class $Proxy22 implements UserService{

Public void checkLogin(){

//追加事务处理

//重写了UserServiceImpl.checkLogin

}

}

 

Public class $Proxy22 extends 目标类{}

 

AOP注解配置

注解的标记

@Component<---- --->    起到应以<bean>的作用

@Aspect    <---- --->    <aop:aspect ref=”loggerBean” >

@Before    <---- --->    <aop:before Pointcut=within()>

 

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.stereotype.Component;

@Component

@Aspect

public class LoggerBean {

@Before("within(cn.tedu.cloudnote.controller..*)")

public void logController(){

System.out.println("AOP功能注入");

}

@Before("within(cn.tedu.cloudnote.service..*)")

public void service(){

System.out.println("service");

}

}

 

实际应用:cloudnote性能审计

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.springframework.stereotype.Component;

@Component

@Aspect

public class AuditBean {

@Around("within(cn.tedu.cloudnote.service..*)")

public Object audit(ProceedingJoinPoint point){

Object obj=null;

try {

long timeStart=System.currentTimeMillis();

//看作每次调用service

obj=point.proceed();

long timeEnd=System.currentTimeMillis();

//获取正在调用的service

String str=point.getSignature().toString(); System.out.println(str+"耗时:"+(timeEnd-timeStart));

} catch (Throwable e) {

e.printStackTrace();

}

return obj;

}

}

 

Obj:打印如下

User:[id=e4f340d64b574aac82aab6547d822baa,name=zj,

password=4QrcOUm6Wau+VuBX8g+IPg==, token=null, nick=ZJ]

 

案例:

要求:当系统发生Service异常,将异常信息写入日志

切面:将异常信息写入文件

切入点:after-throwing(“within(service..*)”)

import java.io.FileWriter;

import java.io.PrintWriter;

import java.text.SimpleDateFormat;

import java.util.Date;

 

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Aspect;

import org.springframework.stereotype.Component;

//扫描到spring容器

@Component

//将该类作为切面的组件

@Aspect

public class ExceptionBean {

//e:目标组件抛出的异常对象

@AfterThrowing(throwing="e",pointcut="within(cn.tedu.cloudnote.service..*)")

public void execute(Exception e){

//将异常信息输入文件

try {

FileWriter fw=new FileWriter("D:\\note_error.log",true);//true,以追加的方式

PrintWriter pw=new PrintWriter(fw);

//利用pw对象写入异常信息

Date time=new Date();

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String timeStr=sdf.format(time);

pw.println("************************************");

pw.println("*异常类型:"+e);

pw.println("*异常时间:"+timeStr);

pw.println("***************异常详细信息*************");

e.printStackTrace(pw);

fw.close();

pw.close();

} catch (Exception ex) {

System.out.println("记录异常失败");

}

}

 

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值