概述:
AOP即Aspect Oriented Programming
意为面向切面编程
AOP的主要功能有日志记录、性能统计、安全控制、事务处理和异常处理
核心概念:
Spring AOP就像一把刀,在代码的执行的过程中,可以随意的插入和拔出。在插入和拔出的位置可以“任意妄为”的做自己喜欢的事。
名称 | 说明 |
---|---|
横切关注点 | 对哪些方法进行拦截,拦截后如何处理 |
切面(Aspect) | 类是对物体特征的抽象,切面就是对横向关注点的抽象 |
连接点(Joinpoint) | 被拦截到的点(方法,字段,构造器) |
切入点(Pointcut) | 对连接点进行拦截的定义 |
通知(Advice) | 拦截到连接点之后要执行的代码,通知分为前置,后置,异常,最终,环绕 |
目标对象 | 代理的目标对象 |
织入(Weave) | 将切面应用到目标对象并导致代理对象创建的过程 |
引入(Introduction) | 在不修改代码的情况下,引用可以在运行期间为类动态的添加一些方法或字段 |
Advice通知类型:
名称 | 说明 |
---|---|
前置通知(Before Advice) | 在连接点前面执行,一般不影响连接点的执行,除非此处抛出异常 |
正返回通知(After Returning Advice) | 在连接点正常执行完成后执行,如果连接点异常,则不会执行 |
异常返回通知(After Throwing Advice) | 在连接点抛出异常后执行 |
后通知(After (finally) Advice) | 在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容 |
环绕通知(Around Advice) | 围绕在连接点前后,环绕通知是最强大的通知类型。环绕通知还需要负责决定是继续处理连接点还是中断执行 |
SpringAOP内部是使用动态代理模式实现的,下面我们通过JDK动态代理模式实现一个最简单的日志框架:
1.首先在HellowHermit项目包com.hermit.test下创建业务接口类BusinessClassService
package com.hermit.test;
public interface BusinessClassService {
void doSomething();
}
2.在com.hermit.test下创建业务的实现类BusinessClassServiceImpl
package com.hermit.test;
public class BusinessClassServiceImpl implements BusinessClassService{
public void doSomething(){
System.out.println("HuaWei number one!");
}
}
3.然后编写日志类接口MyLogger
package com.hermit.test;
import java.lang.reflect.Method;
public interface MyLogger {
/**
* 记录进入方法的时间
*/
void saveIntoMethodTime(Method method);
/**
* 记录推出方法的时间
*/
void saveOutMethodTime(Method method);
}
4.编写MyLoggerImpl实现类
package com.hermit.test;
import java.lang.reflect.Method;
public class MyLoggerImpl implements MyLogger{
@Override
public void saveIntoMethodTime(Method method) {
System.out.println("进入"+method.getName()+"方法的时间为"+System.currentTimeMillis());
}
@Override
public void saveOutMethodTime(Method method) {
System.out.println("退出"+method.getName()+"方法的时间为"+System.currentTimeMillis());
}
}
5.最后,编写最重要的类:MyLoggerHandler
package com.hermit.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyLoggerHandler implements InvocationHandler {
//原始对象
private Object objOriginal;
//关键
private MyLogger myLogger = new MyLoggerImpl();
public MyLoggerHandler(Object object){
super();
this.objOriginal = object;
}
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{
Object result = null;
//日志类的方法:保存进入方法的时间
myLogger.saveIntoMethodTime(method);
//调用代理方法
result = method.invoke(this.objOriginal,args);
//日志类的方法:保存退出方法的时间
myLogger.saveOutMethodTime(method);
return result;
}
}
6.我们来编写一个测试的类MyLoggerTest
package com.hermit.test;
import java.lang.reflect.Proxy;
public class MyLoggerTest {
public static void main(String args[]){
//实例化业务类
BusinessClassService businessClassService = new BusinessClassServiceImpl();
//日志类的handler
MyLoggerHandler myLoggerHandler = new MyLoggerHandler(businessClassService);
//获得代理类对象
BusinessClassService businessClass = (BusinessClassService)
Proxy.newProxyInstance(businessClassService.getClass().
getClassLoader(),businessClassService.getClass().getInterfaces(),
myLoggerHandler);
//执行代理类方法
businessClass.doSomething();
}
}
运行成功如下:
以上是利用JDK动态代理模式实现的简单的日志框架
总结步骤:
1.创建一个实现InvocationHandler接口的类MyLoggerHandler,实现invoke()方法。
2.创建被代理的类BusinessClassService以及接口BussinessClassServiceImpl
3.调用Proxy的静态方法newProxyInstance,创建一个代理类
4.通过代理类调用方法