AOP编程需要导入的架包:
基本的6个架包+以下两个jar包
aopaliance.jar:AOP包
aspectjweaver.jar AspectJ框架提供的规范
一共是以下的包
项目架构
下面以一个小项目来演示基于XML配置的AOP编程
实体类
Student实体 类
package club.johnny.polo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Student {
private int stuNo ;
private String stuName ;
private int stuAge ;
public int getStuNo() {
return stuNo;
}
public void setStuNo(int stuNo) {
this.stuNo = stuNo;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
@Override
public String toString() {
return this.stuNo+","+this.stuName+","+this.stuAge;
}
}
业务类
StudentDao接口
package club.johnny.dao;
import club.johnny.polo.Student;
public interface StudentDao {
void addStudent(Student student);
void deleteStudent(int id);
}
StudentDao实现类StudentImpl
package club.johnny.dao.impl;
import club.johnny.dao.StudentDao;
import club.johnny.polo.Student;
public class StudentDaoImpl implements StudentDao {
public void addStudent(Student student) {
// TODO Auto-generated method stub
System.out.println(" 模拟增加学生……");
//int a=1/0;
}
public void deleteStudent(int id) {
// TODO Auto-generated method stub
System.out.println(" 模拟删除学生……"+id);
}
}
IStudentService接口
package club.johnny.service;
import club.johnny.polo.Student;
public interface IStudentService {
void addStudent(Student student);
void deleteStudent(int id);
}
IStudentService实现类StudentServiceImpl
package club.johnny.service.impl;
import club.johnny.dao.StudentDao;
import club.johnny.polo.Student;
import club.johnny.service.IStudentService;
public class StudentServiceImpl implements IStudentService {
private StudentDao studentDao;
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
public void addStudent(Student student) {
// TODO Auto-generated method stub
studentDao.addStudent(student);
}
public void deleteStudent(int id) {
// TODO Auto-generated method stub
studentDao.deleteStudent(id);
}
}
通知类
通知类AspectBaseOnXml:模拟log日志通知
package club.johnny.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class AspectBaseOnXml {
//前置通知
public void logBefore(JoinPoint joinpoint){
System.out.println("前置通知……");
System.out.println("目标类是:"+joinpoint.getTarget());
System.out.println(",被植入增强处理的目标方法是:"+joinpoint.getSignature().getName());
}
//后置通知
public void logAfterReturning(JoinPoint joinpoint){
System.out.println("后置通知……");
System.out.println(",被植入增强处理的目标方法是:"+joinpoint.getSignature().getName());
}
//环绕通知
public Object logAround(ProceedingJoinPoint proceedingJoinpoin) throws Throwable{
System.out.println("环绕通知实现的[前置通知]……");
//执行被增强方法 该方法会抛出异常 需进行异常捕获
Object obj=proceedingJoinpoin.proceed();
System.out.println("环绕通知实现的[后置通知]……");
return obj;
}
//异常通知
public void logAfterThrowing(JoinPoint joinpoint,Throwable e){
System.out.println("异常通知:"+e.getMessage());
}
//最终通知
public void after() {
System.out.println("最终通知……");
}
}
配置文件
配置 文件applicatioContext.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 http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 目标类 -->
<bean id="studentDao" class="club.johnny.dao.impl.StudentDaoImpl">
</bean>
<bean id="studentService" class="club.johnny.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao">
</property>
</bean>
<!-- 定义切面 -->
<bean id="myaspectBaseOnXml" class="club.johnny.aop.AspectBaseOnXml">
</bean>
<!-- aop编程 -->
<aop:config>
<!-- 配置切面 -->
<aop:aspect ref="myaspectBaseOnXml">
<!-- 配置切点 -->
<aop:pointcut expression="execution(public * club.johnny.service.impl.StudentServiceImpl.addStudent(..))" id="pointcut"/>
<!-- 关联通知和切入点 -->
<!-- 前置通知 -->
<aop:before method="logBefore" pointcut-ref="pointcut"></aop:before>
<!-- 后置通知 在方法返回之后执行 可以获得方法的返回值
returning属性:用于设置后置通知的第二个参数的名称 类型是Object
-->
<aop:after-returning method="logAfterReturning" pointcut-ref="pointcut" returning="returnVal"></aop:after-returning>
<!-- 环绕通知 -->
<aop:around method="logAround" pointcut-ref="pointcut"></aop:around>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
</aop:aspect>
</aop:config>
</beans>
配置过程:
首先需要将通知类、业务类纳入Spring的IOC容器中
<bean id="studentDao" class="club.johnny.dao.impl.StudentDaoImpl">
</bean>
<bean id="studentService" class="club.johnny.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao">
</property>
</bean>
<!-- 定义切面 -->
<bean id="myaspectBaseOnXml" class="club.johnny.aop.AspectBaseOnXml">
</bean>
然后定义切点
<!-- 配置切点 -->
<aop:pointcut expression="execution(public * club.johnny.service.impl.StudentServiceImpl.addStudent(..))" id="pointcut"/>
最后通过pointcut-ref将切点与通知连接起来
<!-- 关联通知和切入点 -->
<!-- 前置通知 -->
<aop:before method="logBefore" pointcut-ref="pointcut"></aop:before>
execution(public * club.johnny.service.impl.StudentServiceImpl.addStudent(..)) *表示任意返回值 “..”表示任意参数列表 若指定类名,需写全类名。
示例:
测试类的测试方法
public static void testAop() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
IStudentService studentService=(IStudentService)context.getBean("studentService");
studentService.addStudent(new Student());
studentService.deleteStudent(2);
}
结果