博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring AOP(一)Spring AOP实现原理简介
阅读量:4159 次
发布时间:2019-05-26

本文共 4592 字,大约阅读时间需要 15 分钟。

我们知道,使用面向对象编程(OOP)有一些弊端,当需要为多个不具有继承关系的对象引入同一个公共行为时,例如日志、安全检测等,我们只有在每个对象里引用公共行为,这样程序中就产生了大量重复代码,所以就有了一个对面向对象编程的补充:面向切面编程(AOP),AOP所关注的方向是横面的,不同于OOP的纵面。

Spring AOP的实现原理是 动态代理,实现方式有两种: JDK动态代理和CgLib动态代理。

JDK动态代理

Jdk动态代理是基于 InvocationHandlerProxy 来实现,由Java内部的 反射 机制来实例化代理对象,并调用委托类方法。

一个JDK实现动态代理的Demo:

  • 目标接口
public interface TestAop {
void process();}
  • 目标实现类
@Componentpublic class TestAopImpl implements TestAop {
@Override public void process() {
System.out.println("testAop.process()"); }}
  • 切面类
@Componentpublic class AopAspect {
public void before() {
System.out.println("前置通知"); } public void after() {
System.out.println("后置通知"); }}
  • 测试类
public class MainTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); final TestAop testAop = ac.getBean(TestAop.class); final AopAspect aopAspect = ac.getBean(AopAspect.class); //创建代理 TestAop testAopProxy = (TestAop) Proxy.newProxyInstance( ac.getClassLoader(), testAop.getClass().getInterfaces(), new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前执行 aopAspect.before(); //执行目标类方法 Object obj = method.invoke(testAop, args); //后执行 aopAspect.after(); return obj; } } ); testAopProxy.process(); }}

输出结果:

前置通知testAop.process()后置通知

CgLib动态代理

基于CGlib 动态代理模式是基于 继承 被代理类生成代理子类,不用实现接口。只需要被代理类是非final 类即可,cglib动态代理底层是借助asm字节码技术。

一个CgLib实现动态代理的Demo:

  • 目标类、切面类都同上
  • 测试类
public class MainTest {
public static void main(final String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); final AopAspect aopAspect = ac.getBean(AopAspect.class); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(TestAopImpl.class); enhancer.setCallback(new MethodInterceptor() {
@Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
aopAspect.before(); Object result = methodProxy.invokeSuper(o, objects); aopAspect.after(); return result; } }); TestAopImpl testAop = (TestAopImpl) enhancer.create(); testAop.process(); }}

输出结果:

前置通知testAop.process()后置通知

Spring AOP

与上述两种编码方式对比:

  • Spring AOP代理是 基于IOC容器 负责生成与管理:切面Bean的创建、通知的应用类、应用时间点等关系也都由IOC容器管理;
  • Spring根据策略判断使用JDK和还是CGLIB实现动态代理,策略规则为:
    1. Spring AOP默认是使用JDK动态代理,如果代理的类没有接口则会使用CGLib代理。
    2. CGLib代理其生成的动态代理对象是目标类的子类,也可以强制使用CGLib模式。

Spring中AOP相关概念

  • 通知(advice):在方法执行之前或之后采取的实际操作。 这是在Spring AOP框架的程序执行期间调用的实际代码片段
  • 连接点(JointPoint):应用程序中使用Spring AOP框架采取操作的实际位置
  • 切点(PointCut):在切点应该执行Advice
  • 切面(Aspect)
  • 引入(Introduction):引用允许我们向现有的类添加新的方法或者属性
  • 织入(Weaving):创建一个被增强对象的过程

Spring中提供了3种类型的AOP支持:

  1. 基于代理的经典Spring AOP,低版本的spring配置方式;

  2. 使用XML配置方式,纯POJO切面,aop命名空间

  3. @AspectJ注解方式:与xml形式的效果相同,是最简洁和最方便的;

有关这三种方式的使用方式及详细介绍:

我们重点分析基于注解方式的Spring AOP实现。首先是一个Demo:

  • 配置文件:
  • 目标接口
public interface TestAop {
void process();}
  • 目标实现类
@Componentpublic class TestAopImpl implements TestAop {
@Override public void process() {
System.out.println("testAop.process()"); }}
  • 切面类
import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;@Component@Aspectpublic class AopAspect {
//定义切点 @Pointcut("execution(* example.aop.*.*(..))") public void aopPointcut() {
} @Before("aopPointcut()") public void before() {
System.out.println("前置通知"); } //后置通知 @After("aopPointcut()") public void after() {
System.out.println("后置通知"); } //环绕通知 @Around("aopPointcut()") public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知:环绕前"); pjp.proceed();//执行方法 System.out.println("环绕通知:环绕后"); }}
  • 测试类
public class MainTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); TestAop testAop = ac.getBean(TestAop.class); testAop.process(); }}

输出结果:

环绕通知:环绕前前置通知testAop.process()环绕通知:环绕后后置通知

转载地址:http://bajxi.baihongyu.com/

你可能感兴趣的文章
设计模式-模板方法模式
查看>>
设计模式-单例模式
查看>>
设计模式-命令模式
查看>>
设计模式-状态模式
查看>>
PowerDesigner快捷键
查看>>
Java多线程之高并发的一些概念
查看>>
Java多线程之基础概念
查看>>
Java多线程之volatile详解
查看>>
Java多线程之synchronized详解
查看>>
Java多线程之ThreadLocal线程局部变量详解
查看>>
Java多线程之无锁原子类和CAS算法
查看>>
Java多线程之并发工具类的使用
查看>>
Java多线程之AbstractQueuedSynchronizer原理解析
查看>>
Java多线程之常用并发容器的使用
查看>>
Docker安装报错container-selinux >= 2.5-11
查看>>
ELK介绍和集群环境安装
查看>>
Java多线程之线程池Executor
查看>>
Java虚拟机之自动内存管理
查看>>
Java虚拟机之内存分配详解
查看>>
Java虚拟机之垃圾收集器
查看>>