在了解SpringAOP之前先来了解下什么是代理模式?
代理模式:是一个使用频率非常高的设计模式,主要是为其他对象提供一种代理以控制对这个对象的访问。
动态代理的步骤:
1. 创建一个实现接口InvocationHandler的类,它必须实现invoke方法;
2.创建被代理的类及接口
3. 通过Proxy的静态方法newProxyInstance(ClassLoaderHandler,Class[] interfaces, InvocationHandler h)创建一个代理
4. 通过代理调用接口方法
举例说明(借鉴网上的例子):
老师让同学A去丢垃圾,同学A不想去,于是叫了同学B帮忙丢,但是同学A又不放心同学B没有把垃圾丢到垃圾桶,所以在一旁监督同学B,在合理的时间做合理的事情,老师就以为是同学A丢的。
创建一个垃圾类:
public interface Rabbish{
//丢垃圾
void doRabbish();
}
操作丢垃圾,目标对象,根据例子来说,这个丢垃圾的操作是同学A也是同学B
public class HimB implements Rabbish{
@Override
public void doRabbish{
System.out.println(“Him doRabbish!!!”);
}
}
驱使目标对象去丢垃圾,即同学A让同学B去丢垃圾
public class MineA implements Rabbish{
private HimB b;
@Override
public void doRabbish(){
//前置通知
System.out.println(“同学A请求同学B帮忙丢垃圾”);
//丢垃圾
try{
b.doRabbish();
}catch(Exception e){
//异常通知
system.out.println(e);
Throw e;
}
//后置通知
System.out.println(“垃圾已丢”);
}
}
接来下了解AOP:
Spring AOP是Spring框架的核心功能之一,面向切面编程,它利用了java代理机制模式实现,其思想就是通过预编译方式和运行期间动态代理实现程序功能(例如登陆权限拦截,监控异常等)的统一维护。它可以将模块划分的更细致,减少各模块和公用模块之间的耦合,让我们将关注点转移到业务本身。
下面来了解下AOP的几个关键词:
1. 切面(Aspect):切面是通知和切点的结合。通知和切点共同定义了切面的全部内容,切面可以使用通用类或者在普通类中定义@Aspect注解来实现。
2. 连接点(join point):指方法,一个连接点总是代表一个方法的执行。应用可能有数以千计的时机应用通知,这些时机称之为连接点。连接点是在应用执行过程中能够插入切面的一个点,这个点可以是调用方法时,抛出异常时等。切面代码可以利用这些点插入到应用到正常流程之中,并添加新的行为。
3. 通知(Advice):切面的工作被称之为通知。
4. 切入点(Pointcut):切点的定义会匹配通知所要织入的一个或多个连接点,我们通常使用明确的类和方法名称,或者利用正则表达式定义所匹配的类和方法名称来指定这些切点。
5. 引入(Introduction):引入允许我们向现有类添加新方法或属性。
6. 目标对象(Target Object):被一个或者多个切面所通知的对象。它通常是一个代理对象。也有人把它叫做被通知对象,既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理对象。
7. 织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。
在SpringAOP中,关注点和横切关注的区别?
关注点(concern)是应用中一个模块的行为,一个关注点可能会被定义为一个我们想实现的一个功能。
横切关注点(cross-cutting concern)是一个关注点,是整个应用都会使用的功能,并影响整个应用,例如日志,安全和数据传输,几乎应用的每个模块都需要的功能。
切面通知的类型:
1. 前置通知(Before):在目标方法被调用之前调用通知功能;
2. 后置通知(after);在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
3. 返回通知(after-returning):在目标方法成功执行之后调用通知;
4. 异常通知(after-throwing):在目标方法抛出异常后调用通知;
5. 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
举例说明AOP登陆拦截:
@Aspect
@Componment
public class LoginAspect{
//切入点
@Pointcut(value=“Execution(public * com.xxx.user ..*.*(..)))”)
public void pointCutMethod(){}
//环绕通知
@Around(value=“pointCutMethod()”)
public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
//业务逻辑处理
//返回方法的返回值
Object proceed = pjp.proceed();
}
}