Spring AOP 实现原理 与CGLIb应用

什么是Spring AOP

Spring AOP 是Spring的核心功能,因为Java是面向对象编程,更多的是一个纵向的,但是遇到存在不存在关联和继承关系的横向关系时,就无法处理。所以这时可以通过切入点,将不相关的逻辑织入到当前业务代码中。

Spring AOP的类型

AOP的代理可分为

  • 静态代理:编译时增强,使用AOP框架提供的命令进行编译,从而在编译阶段生成AOP代理类。
  • 动态代理:运行时增强,借助JDK动态代理、CGLIB在内存中临时生成AOP动态代理类。

Spring 使用了同AspectJ 5 一样的注解,但是并没有 使用AspectJ编译器和织入器(Weaver),底层依然使用的Spring AOP 来实现动态代理生成AOP。

使用Spring AOP 实现AOP

  • 启用注解模式


  • 定义需要处理的Bean
// 使用 @Aspect 定义一个方面类
@Component 
public class Chinese
{ 
   public String sayHello(String name){ 
       System.out.println("-- 正在执行 sayHello 方法 --"); 
       // 返回简单的字符串
       return name + " Hello , Spring AOP"; 
   } 
// 定义一个 eat() 方法
   public void eat(String food){ 
      System.out.println("我正在吃 :"+ food); 
   } 
}
  • 切入增加方法:事务控制、日志记录
  //定义一个切面
@Aspect
public class AfterReturnTest{
  //匹配包下所有的方法执行为切入点
@AfterReturning(return="rvt",pointcut="execution(* cn.com.bluemoon.service.impl.*.*")
  public void log(Object rvt){
    System.out.println("获取目标方法返回值:"+ rvt);
    System.out.println("模拟日制记录...");
  }
}

在程序中增加System.out.println(p.getClass());

代码可以输入p变量所引用对象的实现类,再次执行将看到代码产生class org...**.Chinese$EnhancerByCgLib$$290441d2的输出,这才是p变量所引用的对象的实现类,同时也是Spring AOP动态生成的AOP代理类。

若将上面程序稍作修改:让业务罗积累Chinese类实现一个任意接口例如:

public interface Person 
{ 
String sayHello(String name); 
void eat(String food); 
}

接下来Beantest类面向Person接口、而不是Chinese类编程。

public class BeanTest 
{ 
public static void main(String[] args) 
{ 
// 创建 Spring 容器
ApplicationContext ctx = new 
ClassPathXmlApplicationContext("bean.xml"); 
Person p = ctx.getBean("chinese" ,Person.class);
System.out.println(p.sayHello("张三")); 
p.eat("西瓜"); 
System.out.println(p.getClass()); 
} 
}

执行输出的将会是class$Proxy7,说明AOP代理由JDK动态代理生成。

Spring AOP 动态代理原则

类型 实现方式
CGLIB 目标对象实现类没有实现接口
JDK 目标对象实现了接口

Spring AOP 原理

Spring AOP结构图

如图所示: Spring AOP的代理是由Spring的Ioc容易负责生成、管理,其依赖关系也由Ioc容器负责管理。因此,AOP代理可以直接使用容器中的其他bean实例座位目标,这种关系可由IOC容器的依赖注入提供。
而我们需要做的是:

  • 定义普通业务组件
  • 定义切入点,一个切入点可能横切多个业务组件
  • 定义增强处理(After、Before、Around),AOP框架为普通业务组件织入(weaver)处理动作。

CGLIB 生成代理类

CGLIB(Code Generation Library)即代码生成库。可以在运行时动态的生成某个类的自雷。

AroundAdivice.java : 拦截器实现类
public class AroundAdvice implements MethodInterceptor 
{ 
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy)throws 
 java.lang.Throwable { 
  System.out.println("执行目标方法之前,模拟开始事务 ..."); 
  // 执行目标方法,并保存目标方法执行后的返回值
  Object rvt = proxy.invokeSuper(target, new String[]{"被改变的参数"}); 
  System.out.println("执行目标方法之后,模拟结束事务 ..."); 
  return rvt + " 新增的内容"; 
  } 
}

它的作可以在调用目标方法之前、调用目标方法之后织入增强处理。

ChineseProxyFactory.java:工作类
public class ChineseProxyFactory 
{ 
  public static Chinese getAuthInstance(){ 
    Enhancer en = new Enhancer(); 
    // 设置要代理的目标类
    en.setSuperclass(Chinese.class);
    // 设置要代理的拦截器
    en.setCallback(new AroundAdvice());
    // 生成代理类的实例 
    return (Chinese)en.create();
  } 
}

通过Enhancer 将Chinese类作为目标,以AroundAdvice对象作为ADvice,程序将会生成一个Chinese的子类,这个子类就是CGLIB生成的代理类,作为Chinese对象使用,但它增强了Chinese类的方法。

测试效果:

public class Main 
{ 
public static void main(String[] args) 
{ 
Chinese chin = ChineseProxyFactory.getAuthInstance(); 
System.out.println(chin.sayHello("孙悟空")); 
chin.eat("西瓜"); 
System.out.println(chin.getClass()); 
} 
}
-- 正在执行 sayHello 方法 --

执行目标方法之后,模拟结束事务 ...

被改变的参数 Hello , CGLIB 新增的内容

执行目标方法之前,模拟开始事务 ...

我正在吃 : 被改变的参数

执行目标方法之后,模拟结束事务 ...

class lee.Chinese$$EnhancerByCGLIB$$4bd097d9

小结

AOP广泛应用于处理一些具有横切性质的系统级服务,AOP的出现是对OOP的补充,它是的开发者能用更优雅的方式处理具有横切性质的服务。

你可能感兴趣的:(Spring AOP 实现原理 与CGLIb应用)