Spring5企业级开发实战(六)————SpringAOP概述及CGLIB实现

本文深入讲解面向切面编程(AOP)的基本概念与实践应用,包括切面、连接点、切入点等核心要素,通过CGLIB动态代理实现AOP,演示如何使用XML配置和注解方式在Spring框架中实现AOP,帮助读者理解并掌握AOP编程技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AOP联盟

面向切面编程(AOP)是一种编程技术,AOP联盟定义了一套用于规范AOP实现的底层API,现在已经推出了几个项目。

  • ASM 轻量级字节码转换器
  • AspectJ 一个面向切面的框架,拓展了JAVA语言
  • CGLIB 用于类工件操作和方法拦截器的高级API
  • JBoss-AOP 拦截和基于元数据的AO框架

AOP概述

面向切面编程是对面向对象编程的一种补充,面向切面编程提供了一种横向的切面逻辑,将与多个对象有关的公共模块分装成一个可重用模块。

  • 横切关注点:一些具有横切多个不同软件模块的行为,横切关注点可以对某些方法进行拦截,拦截后对方法进行增强。
  • 切面(Aspect):切面就是对横切关注点的抽象,这个切面可能切多个对象。
  • 连接点(JoinPoint):连接点就是在程序执行过程中某个特定的点
  • 切入点(PointCut):切入点是匹配连接点的拦截规则,在满足这个切入点连接点上运行通知。
  • 通知(Advice):见切入点
  • 目标对象(TargetObject):需要被切的对象
  • 织入(Weaving):织入是把切面作用到目标对象,产生一个代理对象的过程
  • 引入(Introduction):引入是在程序运行时给一个类声明额外的方法或者属性,即不需要为类实现一个接口,就能使用接口中的方法或者属性。

AOP实现

基于CGLIB动态代理的实现
  • XML配置方式实现
    以下是代码:
    接口类
 package com.SpringAOP;
/**
 * Author:haozhixin
 * Func:  AOPXML实现
 * Date:  20190808
 */
public interface Fruit {
	void eat();
}

Apple类

package com.SpringAOP;
/**
 * Author:haozhixin
 * Func:  AOPXML实现
 * Date:  20190808
 */
public class Apple implements Fruit {
	@Override
	public void eat() {
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("吃苹果");
	}
}

Banana类

package com.SpringAOP;
/**
 * Author:haozhixin
 * Func:  AOPXML实现
 * Date:  20190808
 */
public class Banana implements Fruit{
	@Override
	public void eat() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("吃香蕉");
	}
}

FruitHandler

package com.SpringAOP;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Author:haozhixin
 * Func: 横切关注点,关注分别用了多长时间吃水果
 * Date: 20190808
 */
public class FruitHandler {
	public void StartEatFruit(){
		System.out.print("开始吃水果的时间是:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
	}
	public void EndEatFruit(){
		System.out.print("开始吃水果的时间是:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
	}
}

SpringAopTest.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.SpringAOP"></context:component-scan>
    <bean id="Apple" class="com.SpringAOP.Apple" scope="singleton" >
    </bean>
    <bean id="Banana" class="com.SpringAOP.Banana" scope="singleton" >
    </bean>
    <bean id="FruitHandler" class="com.SpringAOP.FruitHandler" scope="singleton" >
    </bean>

    <aop:config proxy-target-class="true"><!--一定要声明,不然main函数会报错,网上大部分解释都是错误的-->
        <aop:aspect id="dateLog" ref="FruitHandler"><!--切面-->
            <aop:pointcut id="eatFruit" expression="execution(* com.SpringAOP.Fruit.*(..))"/> <!--切点--> <!--注意第一个* 后边有空格-->
            <aop:before method="StartEatFruit" pointcut-ref="eatFruit"></aop:before>
            <aop:after method="EndEatFruit" pointcut-ref="eatFruit"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

SpringAopTest类

import com.SpringAOP.Apple;
import com.SpringAOP.Banana;
import com.SpringAOP.Fruit;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Author:haozhixin
 * Func:
 * Date:
 */
public class SpringAopTest {
	public static void main(String []args){
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:SpringAopTest.xml");
		Fruit apple = (Apple)applicationContext.getBean("Apple");
		Fruit banana = (Banana)applicationContext.getBean("Banana");
		apple.eat();
		System.out.println("-----休息一会------");
		banana.eat();
	}
}

  • 注解方式实现
    以下是代码

FruitAnnotationHandler类

package com.SpringAOP;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Author:haozhixin
 * Func: SpringAOP  注解实现
 * Date: 20190808
 */
@Component
@Aspect
public class FruitAnnotationHandler {
	@Pointcut("execution(* com.SpringAOP.Fruit.*(..))")
	public void eatFruit(){}

	/***
	 * 前置通知
	 */
	@Before("eatFruit()")
	public void StartEatFruit(){
		System.out.print("开始吃水果的时间是:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
	}

	/***
	 * 后置通知
	 */
	@After("eatFruit()")
	public void EndEatFruit(){
		System.out.print("开始吃水果的时间是:"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
	}
}

SpringAnnotationAopTest.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.SpringAOP"></context:component-scan>
    <bean id="Apple" class="com.SpringAOP.Apple" scope="singleton" >
    </bean>
    <bean id="Banana" class="com.SpringAOP.Banana" scope="singleton" >
    </bean>
    <bean id="FruitAnnotationHandler" class="com.SpringAOP.FruitAnnotationHandler" scope="singleton" >
    </bean>
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy><!--必须声明,不然切面不会生效-->
</beans>

SpringAnnotationAopTest

package com.Bean生命周期;

import com.SpringAOP.Apple;
import com.SpringAOP.Banana;
import com.SpringAOP.Fruit;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Author:haozhixin
 * Func:
 * Date:
 */
public class SpringAnnotationAopTest {
	public static void main(String []args){
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:SpringAnnotationAopTest.xml");
		Fruit apple = (Apple)applicationContext.getBean("Apple");
		Fruit banana = (Banana)applicationContext.getBean("Banana");
		apple.eat();
		System.out.println("-----休息一会------");
		banana.eat();
	}
}

以上就是基于CGLIB动态代理的相关AOP实现,如果对JDK感兴趣的同学可以自行百度搭建,这里不再赘述了~谢谢大家!


作者:select you from me
来源:优快云
转载请联系作者获得授权并注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值