一、 项目介绍
1、AOP面向切面编程基于xml配置方式–通知/增强案例
2、项目开发工具:
(1) jdk1.8.0_92
(2) IDEA-2019.3.4
(3) apache-maven-3.5.2
3、项目目录结构
二、源码
1、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>com.sou</groupId>
<artifactId>spring_aop</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!--单元测试-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Spring的junit测试集成-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<!-- spring四大核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<!-- AOP依赖-->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<!-- 日志依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<!-- 配置jdk编译插件和tomcat插件-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<!--<configuration>
<!–修改端口号–>
<port>8888</port>
<!–你的项目路径–>
<path>/</path>
</configuration>-->
</plugin>
</plugins>
</build>
</project>
2、resources中的配置文件
(1) log4j.properties(日志相关配置信息)
log4j.rootLogger=DEBUG,A1
log4j.logger.org.mybatis=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
(2) applicationContext.xml(Spring实体bean配置文件)
<?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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 配置注解扫描,作用会自动扫描某包或子包下面含有@Component的类,并作为bean来管理-
-->
<context:component-scan base-package="com.sou"/>
<!-- 确定目标xml-->
<bean id="userDao" class="com.sou.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.sou.service.impl.UserServiceImpl"/>
<!-- 配置通知的bean-->
<bean id="myAspect" class="com.sou.aspect.MyAspect"/>
<!-- 配置切入点与切面-->
<aop:config>
<!-- 配置切入点(其实就是拦截哪些方法)以service结尾的bean。 进行增强-->
<aop:pointcut id="myPointcut" expression="bean(*Service)"/>
<!-- 配置切面:关联切入点和切面,要对哪些方法进行怎么样的增强。ref: 目标到增强的类-->
<aop:aspect ref="myAspect">
<!--配置前置通知
method:该增强调用的通知类中的方法名(MyAspect)
pointcut-ref:关联的切入点-->
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after-returning method="after" pointcut-ref="myPointcut" returning="returnVal"/>
<!--异常通知、抛出通知
throwing :配置方法中接收异常的参数的名称,必须和方法中的参数名字一致! ! !-->
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="ex"/>
</aop:aspect>
<!-- 最终通知-->
<!-- <aop:after method="after" pointcut-ref="myPointcut" />-->
</aop:config>
</beans>
3、pojo(实体)层:
User.java
package com.sou.pojo;
public class User {
private String name;
private int age;
}
4、aspect层(接入点):
package com.sou.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspect {
// 前置通知
// 参数:连接点,就是可以拦截到的方法(方法和目标的包装类型)
// 需求:权限控制(权限不足,抛出异常)、记录方法调用信息日志
public void before(JoinPoint joinPoint) {
System.out.println("前置增强方法。。。");
// 每次运行的时候,都获取到其它信息
System.out.println("增强的对象:" + joinPoint.getTarget().getClass().getName());
// 获取连接点的签名:即方法
System.out.println("增强的方法:" + joinPoint.getSignature().getName());
if ("find".equals(joinPoint.getSignature().getName())) {
//根据方法名字进行匹配,find方法与增强的方法名不一样的话,就没权访问这个方法
throw new RuntimeException("当前用户没有权限执行该方法");
}
}
//后置通知:会在方法执行之后拦截增强
//需求:与业务相关的,如网上营业厅查询余额后,自动下发短信。
//参数1:连接点,参数2:返回值类型object,参数名,“随意”,也不能太随意,配置的时候,还要用这个名字
public void after(JoinPoint joinPoint, Object returnVal) {
System.out.println("后置增强方法。。。");
System.out.println("后置通知:系统日志:当前下发了短信的方法是:" + joinPoint.getSignature().getName());
//获取到查询的结果,然后调用发送短信的方法
System.out.println("开始发短信了,短信内容:客户你好,您的余额为:" + returnVal);
}
//环绕通知:在方法的前后拦截增
// 需求:日志、缓存、权限、性能监控、“事务管理”
//有三个特点:
//参数: ProceedingJoinPoint正在执行的连接点
//必须抛出一个异常Throwable
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//在方法之前开启事务
System.out.println("开启了事务。。。");
//目标方法的执行
Object object = proceedingJoinPoint.proceed();
//在目标对象方法执行之后,提交事务
System.out.println("提交了事务。。。");
//要将目标对象返回回去
return object;
}
//抛出通知:在目标对象的方法发生异常的情况下,拦截增强
//需求:处理异常(-般不可预知),记录日志,通知管理员(短信、邮件)
//参数1:连接点信息,参数2:异常, Throwable类型,参数名称,“随意”,配置这个名字
public void
afterThrowing(JoinPoint joinPoint, Throwable ex) {
//-旦发生异常,就将异常的信息打印,或发送给管理员
System.out.println("尊敬的管理员,发生了异常了,发生异常的类是: "
+ joinPoint.getTarget().getClass().getSimpleName()
+ "发生异常的方法是: " + joinPoint.getSignature().getName()
+ ",异常信息为: " + ex.getMessage());
}
}
5、service层
UserService.java
package com.sou.service;
import com.sou.pojo.User;
public interface UserService {
public User login();
public void save();
}
6、service实现层
UserServiceImpl.java
package com.sou.service.impl;
import com.sou.dao.UserDao;
import com.sou.pojo.User;
import com.sou.service.UserService;
import javax.annotation.Resource;
public class UserServiceImpl implements UserService {
@Resource(name = "userDao")
private UserDao userDao;
@Override
public User login() {
System.out.println("这是UserServiceImpl的登录方法");
userDao.login();
return null;
}
@Override
public void save() {
System.out.println("业务层:添加商品异常");
int a = 1 / 0;
}
}
7、dao层(此中只写了简单输出语句,没与数据库交互)
UserDao.java
package com.sou.dao;
import com.sou.pojo.User;
public interface UserDao {
public User login();
}
8、dao实现层
UserDaoImpl.java
package com.sou.dao.impl;
import com.sou.dao.UserDao;
import com.sou.pojo.User;
public class UserDaoImpl implements UserDao {
@Override
public User login() {
System.out.println("这是UserDaoImpl登录方法");
return null;
}
}
9、UserTest文件
SpringAopTest.java
import com.sou.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringAopTest {
// 引入userService对象
@Resource(name = "userService")
private UserService userService;
@Test
public void SpringAopTest() {
userService.login();
userService.save();
}
}
10、运行截图
源码,以及导入项目到自己的idea中,可以地下评论留下QQ号,看到后会及时回复,也可以加qq群:586012641 交流,谢谢