Spring 相关 AOP XML
定义之前说到了Spring的DI,我在DI代码的基础上直接进行了修改操作,配置了AOP 面向切面开发,先说一下AOP的作用以及好处吧:
DI能够让相互协作的软件组件保持松散耦合,而面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。
面向切面编程往往被定义为促使软件系统实现关注点分离的一项技术。
比如在 一个方法执行之前,你需要通知开始了,执行之后,你需要通知结束了。
就算将这两个通知封装成为两个函数,那也需要在需要这些通知的地方进行调用,与上方的直接添加代码无任何区别。
这个时候就出现了AOP来简化代码。只需要一个简单的配置文件或者配置类,这次讲的是配置文件的形式来配置AOP,也就是XML。
先上一个代码
package com.core.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.converter.json.GsonBuilderUtils;
import org.w3c.dom.ls.LSOutput;
/**
* @Auther WangYifei
* @To LiuXuemei
* @Date 2020/2/10 13:41
*/
public class Employee {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("config.xml");
WangYifei wangYifei = classPathXmlApplicationContext.getBean(WangYifei.class);
if (wangYifei.getConfig() != null) {
wangYifei.getConfig().sayOk();
}
}
}
class Config{
public void sayOk(){
System.out.println("Hello World!");
}
}
class AopSing{
public void beforeSing(){
System.out.println("我开始了...");
}
public void afterSing(){
System.out.println("我结束了...");
}
}
class WangYifei{
private Config config;
WangYifei(Config config){
this.config = config;
}
public Config getConfig() {
if(this.config == null){
System.out.println("我没有注入成功");
return this.config;
}else {
System.out.println("我注入进来了 -> " + this.config);
return this.config;
}
}
}
这边在之前的基础上,多了一个 AopSing的类,这里面定义了两个方法,一个是beforeSing,一个是afterSing
分别代表着,执行之前的通知,和执行之后的通知。
我们需要达到的效果,在sayOK() 之前通知,我开始了sayOK() 执行完毕之后通知,我结束了。
无非是加了一个新的类,怎么实现这样的效果呢,就需要配置了,下方给出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: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-3.2.xsd">
<bean id="wangyifei" class="com.core.spring.test.WangYifei">
<constructor-arg ref="configBean"></constructor-arg>
</bean>
<bean id="configBean" class="com.core.spring.test.Config">
</bean>
<bean id="aopsing" class="com.core.spring.test.AopSing">
</bean>
<aop:config>
<aop:aspect ref="aopsing">
<aop:pointcut id="sayok" expression="execution(* *.sayOk(..))"/>
<aop:before method="beforeSing" pointcut-ref="sayok" />
<aop:after method="afterSing" pointcut-ref="sayok" />
</aop:aspect>
</aop:config>
</beans>
一眼就可以看出,多了 aopsing 和 aop:config 的标签 aopsing,不用说,声明了一个bean,并且指定为AopSing这个类。
<aop:config />这个标签看名字也可以看出来是 配置aop的
在<aop:aspect /> 标签引用了aopsing 这个bean
在<aop:pointcut /> 标签定义切点,并配置expression属性来选择所应用的通知。这边选择的就是sayOK()方法
在<aop:before /> 标签定义aopsing 中的方法 method 属性:beforeSing 与 AopSing类中的方法名一致,并引用切点,表示在什么位置进行前置通知,这里的id 使用的是 切点的id : sayok,与上方的pointcut一致。
在<aop:after /> 标签定义aopsing 中的方法,method 属性:afterSing 与 AopSing类中的方法名一致,并引用切点,表示在什么位置进行后置通知,这里的id 使用的是切点的id:sayok,与上方的pointut id 一致。
==这里需要强调一下,一定需要jar包支持,作者一开始在学习的时候,发现没有引入aop的jar包,所以NotFound,因为我用的是maven为基础项目的,所以直接在pom.xml里面添加一下依赖就行了。需要的也可以直接复制下方的:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
之后再次运行,打印结果如下:
16:35:11.482 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@12bb4df8
16:35:11.765 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 7 bean definitions from class path resource [config.xml]
16:35:11.804 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator'
16:35:11.893 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'wangyifei'
16:35:11.894 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#0'
16:35:12.050 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#1'
16:35:12.059 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'configBean'
16:35:12.189 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'aopsing'
我注入进来了 -> com.core.spring.test.Config@7586beff
我注入进来了 -> com.core.spring.test.Config@7586beff
我开始了...
Hello World!
我结束了...
可以看到在打印Hello World!之前通知了,我开始了,之后通知了,我结束了。目的完成。
这就是AOP的一种,XML配置文件的形式实现。