AOP的概念
AOP(Aspect-Oriented Programming,面向方面编程),可以说是**OOP(Object-Oriented Programing,面向对象编程)**的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需 要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。
AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为
“Aspect”
实现AOP的技术,主要分为两大类:
一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>nadoutong</groupId>
<artifactId>spring_day04_aop</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- bean.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 https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--将连接点,通知纳入到ioc容器中-->
<bean id="accountService" class="com.nadoutong.service.impl.AccountServiceImpl"></bean>
<bean id="logger" class="com.nadoutong.util.Logger"></bean>
<!--配置AOP功能
实现步骤:
1.把通知bean交给spring管理
2.使用aop:config便签表明开始aop配置
3.使用aop:aspect 标签配置切面
属性 id:给切面一个唯一标识(自定义)
ref:指定通知bean的id
4.在aop:aspect 标签体里面配置通知类型
配置前置通知before:
属性 method:配置通知类中的某一个方法的名称 该方法认为是前置通知
pointcut:配置切入点,需要用切入点表达式 含义就是表示对那个方法进行增强
切入点表示写法:
关键字:excution(表达式)
表达式:
访问修饰符 返回值类型 包名..类名.方法名(参数...)
表达式优化:
访问修饰符可以省略
返回值可以使用通配符*(读懂*必须导入包aspectjweaver)
包名也可以使用通配符*
如果表示多层包,可以使用..表示当前包和它的子包
* *.. 类名.方法名(参数1,参数2..)
类名也可以使用通配符*表示任意类
* *..*.方法名(参数1,参数2..)
方法名也可以使用通配符*
* *..*.*(参数1,参数2..)
多个参数使用具体的类型即可
* *..*.*(int,double)
多个参数也可以使用通配符..
* *..*.*(..)
常用写法
com.nadoutong.service.impl.*.*(..)
-->
<aop:config>
<aop:aspect id="logAdvice" ref="logger">
<!-- <aop:before method="advice" pointcut="execution(public void com.nadoutong.service.impl.AccountServiceImpl.transfer())"></aop:before>-->
<aop:before method="advice" pointcut="execution(* *..*.*(..))"></aop:before>
</aop:aspect>
</aop:config>
</beans>
- service包
package com.nadoutong.service;
public interface AccountService {
void transfer(int a,double b);
}
package com.nadoutong.service.impl;
import com.nadoutong.service.AccountService;
public class AccountServiceImpl implements AccountService {
public void transfer(int a,double b) {
System.out.println("转账成功");
}
}
- util包
package com.nadoutong.util;
public class Logger {
public void advice(){
System.out.println("织入成功");
}
}
- 测试
package com.nadoutong;
import com.nadoutong.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AOPTest {
@org.junit.Test
public void test01(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
AccountService accountService=(AccountService)applicationContext.getBean("accountService");
accountService.transfer(1,2);
}
}
测试结果: