AOP(Aspect Orient Programming)是面向切面编程,作为面向对象编程的一种补充,已经成为一种比较成熟的编程方式。面向切面编程将程序运行过程分解成各个切面;AOP专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在JavaEE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等
AOP的核心思想是:将很多业务都要使用的功能进行抽取,在运行业务时; 再动态的植入这些抽取的代码。(将共性业务和核心业务分离).AOP实现了共性功能和核心功能的解耦;提高了共性功能的代码的复用率
AOP和OOP互为补充,面向切面编程将程序运行过程分解成各个切面
值得注意的是:AOP是一种设计思想,与具体的技术无关。
a、切面(Aspect):是一个类,是对横切关注点的抽象;切面用于组织多个Advice,Advice放在切面中定义。
b、连接点(JoinPoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出。在Spring AOP中,连接点总是方法的调用。
c、切入点(Pointcut):匹配连接点的拦截规则。AOP的核心;可以插入增强处理的连接点。简而言之,当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成了切入点。
d、通知(Advice):在切面上拦截到某个特定的连接点之后执行的动作
e、目标对象(Target Objcet):被一个或多个切面所通知的对象,即业务中需要进行增强的业务对象
f、织入(Weaving):将切面作用到目标对象上,然后产生一个代理对象的过程
g、引入(Introduction):用来在运行时给一个类声明额外的方法或属性,即不需要为类实现一个接口 就能使用接口中的方法。
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.4version>
dependency>
在这里;创建Dog、Fish实例;他们都有同一个放法eatFood();在这里以时间为切入点做示例
package com.aop;
/**
* @author Una
* @date 2022/8/11 17:34
* @description:
*/
public class Fish {
public void eatFood(){
System.out.println("开始吃鱼食!!!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("吃完了鱼食!!!");
}
}
package com.aop;
/**
* @author Una
* @date 2022/8/11 17:37
* @description:
*/
public class Dog {
public void eatFood(){
System.out.println("开始吃狗粮!!!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束吃狗粮!!!");
}
}
切面文件
package com.aop;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author Una
* @date 2022/8/11 17:40
* @description:定义切面---即横向关注点(开始和结束的时间)
*/
public class XmlSpilt {
//打印开始的时间
public void startTime(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String startEatDate = sdf.format(new Date());
System.out.println("开始时间是:"+startEatDate);
}
//打印结束的时间
public void endTime(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String startEatDate = sdf.format(new Date());
System.out.println("结束时间是:"+startEatDate);
}
}
xml格式的配置则需要在resource包下创建spring配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="fish" class="com.aop.Fish"/>
<bean id="dog" class="com.aop.Dog"/>
<bean id="xmlSpilt" class="com.aop.XmlSpilt"/>
<aop:config>
<aop:aspect id="dateLog" ref="xmlSpilt">
<aop:pointcut id="eatFood" expression="execution(* com.aop.*.*(..))"/>
<aop:before method="startTime" pointcut-ref="eatFood"/>
<aop:after method="endTime" pointcut-ref="eatFood"/>
aop:aspect>
aop:config>
<aop:aspectj-autoproxy proxy-target-class="true"/>
beans>
测试文件
/**
* @author Una
* @date 2022/8/11 17:47
* @description:
*/
public class XmlSpiltTest {
@Test
public void test2(){
ApplicationContext ac=new ClassPathXmlApplicationContext("aop-conf.xml");
Fish fish=(Fish) ac.getBean("fish");
Dog dog=(Dog) ac.getBean("dog");
fish.eatFood();
System.out.println("----------------------");
dog.eatFood();
}
}
如果采用注解的方式实现;在xm文件中;将不用配置
a、@Aspect注解:表示切面(类,由横切关注点抽象的类)
b、@Pointcut注解:表示指定切入点
c、@Before注解:表示前置通知
d、@After注解:表示后置通知
e、在配置中开启注解的扫描
f、开启aop注解
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.aop"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
beans>
package com.aop;
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 Una
* @date 2022/8/11 17:40
* @description:定义切面---即横向关注点(开始和结束的时间)
*/
@Component
@Aspect
public class XmlSpilt {
//定义切入点方法
@Pointcut("execution(* com.aop.*.*(..))")
public void eatFood(){
}
//打印开始的时间
@Before("eatFood()")
public void startTime(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String startEatDate = sdf.format(new Date());
System.out.println("开始时间是:"+startEatDate);
}
//打印结束的时间
@After("eatFood()")
public void endTime(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String startEatDate = sdf.format(new Date());
System.out.println("结束时间是:"+startEatDate);
}
}
在Dog、Fish类中加入注解@Component
package com.aop;
import org.springframework.stereotype.Component;
/**
* @author Una
* @date 2022/8/11 17:37
* @description:
*/
@Component
public class Dog {
public void eatFood(){
System.out.println("开始吃狗粮!!!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束吃狗粮!!!");
}
}
///
package com.aop;
import org.springframework.stereotype.Component;
/**
* @author Una
* @date 2022/8/11 17:34
* @description:
*/
@Component
public class Fish {
public void eatFood(){
System.out.println("开始吃鱼食!!!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("吃完了鱼食!!!");
}
}
结果: