掌握基于XML的AOP实现,能够基于XML的方式实现Spring AOP
使用AOP代理对象的好处
因为Spring AOP中的代理对象由loC容器自动生成,所以开发者无须过多关注代理对象生成的过程,只需选择连接点、创建切面、定义切点并在XML文件中添加配置信息即可。Spring提供了一系列配置Spring AOP的XML元素。
1.配置Spring AOP的XML元素
2.配置切面
在Spring的配置文件中,配置切面使用的是<aop:aspect>元素,该元素会将一个已定义好的Spring Bean转换成切面Bean,因此,在使用<aop:aspect>元素之前,要在配置文件中先定义一个普通的Spring Bean。Spring Bean定义完成后,通过<aop:aspect>元素的ref属性即可引用该Bean。配置<aop:aspect>元素时,通常会指定id和ref两个属性。
<aop:aspect>元素的id属性和ref属性的描述
3.配置切入点
在Spring的配置文件中,切入点是通过<aop:pointcut>元素来定义的。当
<aop:pointcut>元素作为<aop:config>元素的子元素定义时,表示该切入点是全局的,它可被多个切面共享;当<aop:pointcut>元素作为<aop:aspect>元素的子元素时,表示该切入点只对当前切面有效。定义<aop:pointcut>元素时,通常会指定id、expression属性。
<aop:pointcut>元素的id属性和expression属性描述
Spring AOP切入点表达式的基本格式
execution表达式各部分参数说明
4.配置通知
在Spring的配置文件中,使用<aop:aspect>元素配置了5种常用通知,分别为前置通知、后置通知、环绕通知、返回通知和异常通知。
<aop:aspect>元素的常用属性
代码示例:
pom.xml
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
package cn.hdc.demo3.dao.impl;
import cn.hdc.demo3.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void insert() {
System.out.println("添加用户信息");
}
@Override
public void delete() {
System.out.println("删除用户信息");
}
@Override
public void update() {
System.out.println("更新用户信息");
}
@Override
public void select() {
System.out.println("查询用户信息");
}
}
package cn.hdc.demo3.dao;
public interface UserDao {
public void insert();
public void delete();
public void update();
public void select();
}
package cn.hdc.demo3.entity;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
//切面
public class XmlAdvice {
/**
* @param joinpoint 内部封装了切入点的相关信息
*/
public void before(JoinPoint joinpoint) {
System.out.println("前置通知");
System.out.println("目标类:" + joinpoint.getTarget());
System.out.println("切入点的方法名:" + joinpoint.getSignature().getName());
}
public void after(JoinPoint joinPoint) {
System.out.println("后置通知");
}
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("自定义环绕通知111,在切入点之前执行");
//执行原有功能
Object res = pjp.proceed();
System.out.println("自定义环绕通知222,在切入点之后执行");
//返回原有方法的返回值
}
public void after_returning() {
System.out.println("返回通知,返回值结束才会执行(如果出现异常,不会执行)");
}
public void after_throwing(){
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:content="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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- userDao对象-->
<bean id="userDao" class="cn.hdc.demo3.dao.impl.UserDaoImpl"></bean>
<!-- 增强所在类的对象,切面类对象-->
<bean id="xmlAdvice" class="cn.hdc.demo3.entity.XmlAdvice"></bean>
<!-- aop配置-->
<!-- aop配置根标签,声明开始aop配置-->
<!-- aop配置核心一句话:在切面中配置切点和增强的关系-->
<aop:config>
<!-- 第一个*代表任意返回值,第二个*代表所有方法 (..)表示任意参数-->
<!-- 全局的切入点-->
<aop:pointcut id="pointcut" expression="execution(* cn.hdc.demo3.dao.impl.UserDaoImpl.*(..))"/>
<!-- 配置切面-->
<aop:aspect ref="xmlAdvice">
<!-- 配置关系-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<!-- 相当于finally,发生异常也会执行-->
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
<!-- 环绕通知-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
<!-- 返回通知-->
<aop:after-returning method="after_returning" pointcut-ref="pointcut"></aop:after-returning>
<!-- 异常通知-->
<aop:after-throwing method="after_throwing" pointcut-ref="pointcut"></aop:after-throwing>
</aop:aspect>
</aop:config>
<!-- <bean id="bean2" class="cn.hdc.factory.MyBeanFactory" factory-method="createBean"></bean>-->
<!-- 实例工厂实例化-->
<!-- <bean id="factory" class="cn.hdc.factory.MyBeanFactory"></bean>-->
<!-- <bean id="bean3" factory-bean="factory" factory-method="createBean"></bean>-->
<!-- <bean id="bean4" class="cn.hdc.beans.Bean4">-->
<!-- <constructor-arg value="hello"/>-->
<!-- </bean>-->
</beans>