1.什么是AOP
面向切面编程
2.AOP在spring中的作用
提供声明式事务:允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。日志、事务等
- 切面:横切关注点被模块化的特殊对象。即,他是一个类。log类
- 通知:切面必须要完成的工作。即,类中的方法。log类中的方法
- 目标:被通知对象
- 代理:向目标对象应用通知后创建对象
- 切入点:切面通知执行的地点
- 连接点:与切面匹配的执行点
导入jar包
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
使用方法一:使用原生SpringAPI接口
配置AOP:需要导入AOP约束
1.创建目标对象
public interface UserService { void add(); void delete(); void update(); void select(); }
public class UserServiceImpl implements UserService { public void add() { System.out.println("增加了一个新用户"); } public void delete() { System.out.println("删除了一个新用户"); } public void update() { System.out.println("修改了一个新用户"); } public void select() { System.out.println("查询了一个新用户"); } }
2.实现接口方式创建通知
public class Log implements MethodBeforeAdvice { public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName() + "的" + method.getName() + "方法"); } } public class AfterLog implements AfterReturningAdvice { public void afterReturning(Object o, Method method, Object[] objects, Object target) throws Throwable { System.out.println(target.getClass().getName() + "的" + method.getName() + "方法"); } }
3.在配置文件中创建bean对象
<bean id="userService" class="com.jiabowen.service.UserServiceImpl"></bean> <bean id="log" class="com.jiabowen.log.Log"></bean> <bean id="afterLog" class="com.jiabowen.log.AfterLog"></bean>
4.引入名称空间
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
5.使用AOP织入
<aop:config> <aop:pointcut id="pointcut" expression="execution(* com.jiabowen.service.UserServiceImpl.*(..))"/> <aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"></aop:advisor> </aop:config>
整体
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd "> <bean id="userService" class="com.jiabowen.service.UserServiceImpl"></bean> <bean id="log" class="com.jiabowen.log.Log"></bean> <bean id="afterLog" class="com.jiabowen.log.AfterLog"></bean> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.jiabowen.service.UserServiceImpl.*(..))"/> <aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"></aop:advisor> </aop:config> </beans>
6.测试
使用方式二:自定义实现AOP
1.创建方法实现通知:普通方法
public class diy { public void before(){ System.out.println("方法前"); } public void after(){ System.out.println("方法后"); } }
2.配置文件中
2.1引入名称空间:aop
2.2创建bean
<bean id="userService" class="com.jiabowen.service.UserServiceImpl"></bean> <bean id="diy" class="com.jiabowen.log.diy"></bean>
2.3配置AOP
<aop:config> <aop:aspect ref="diy"> <aop:pointcut id="diyPointCut" expression="execution(* com.jiabowen.service.UserServiceImpl.*(..))"></aop:pointcut> <aop:before pointcut-ref="diyPointCut" method="before"></aop:before> <aop:after pointcut-ref="diyPointCut" method="after"></aop:after> </aop:aspect> </aop:config>
- 配置切面<aspect>:通常是一个类,里面可以定义切入点和通知
- 配置切点<pointCut>
- 配置通知
使用方式三:使用注解实现
3-1
- @Aspect:配置切面
- @Before:配置前置通知,切入点表达式。其他通知同理
@Aspect public class AnnotationPointCut { @Before("execution(* com.jiabowen.service.UserServiceImpl.*(..))") public void Before(){ System.out.println("===方法调用之前==="); } @After("execution(* com.jiabowen.service.UserServiceImpl.*(..))") public void After(){ System.out.println("===方法调用之后==="); } }
配置文件
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd "> 开启注解支持 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 注册bean <bean id="pointCut" class="com.jiabowen.diy.AnnotationPointCut"></bean> <bean id="userService" class="com.jiabowen.service.UserServiceImpl"></bean> </beans>
3-2:如果不想在配置文件中注册bean可以使用@Component
- 配置文件中
- 开启注解支持
- 开启自动注解扫描
- 选择自动扫描的包
<?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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd "> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <context:annotation-config></context:annotation-config> <context:component-scan base-package="com.jiabowen.*"></context:component-scan> </beans>
- 自定义通知类、实体类中添加@Component
@Aspect @Component public class AnnotationPointCut { @Before("execution(* com.jiabowen.service.UserServiceImpl.*(..))") public void Before(){ System.out.println("===方法调用之前==="); } @After("execution(* com.jiabowen.service.UserServiceImpl.*(..))") public void After(){ System.out.println("===方法调用之后==="); } }
@Component public class UserServiceImpl implements UserService { public void add() { System.out.println("增加了一个新用户"); } public void delete() { System.out.println("删除了一个新用户"); } public void update() { System.out.println("修改了一个新用户"); } public void select() { System.out.println("查询了一个新用户"); } }