SpringAOP的注解配置
一、什么是SpringAOP
1.SpringAop是一种编程方式(面向切面编程),不是编程语言
2.解决特定的问题,不能解决所有的问题
3.是OOP的补充,而不是替代
二、解决了什么问题
1.减少了代码的重复性问题
2.关注点的分离。将非功能性代码与功能性代码分离,开发者专注业务模块的开发
三、适用场景
四、SpringAOP的使用
4.1 理解使用的思路
SpringAOP是一种面向切面的编程方式,使用的过程需要了解出切面的表达式(即需要了解拦截哪些方法和那些类),切面的内容。在得到切面之后,植入的非功能性代码。使用的两个步骤:1.根据切面表达式,获取需要拦截的方法。2.根据需求植入代码。
4.2 主要的注解
@Aspect声明切面类,@PointCut声明切入目标@Advice通知
@Before,前置通知;
@After(finally),后置通知,方法执行完成之后;
@AfterReturning,返回通知,成功执行之后执行;
@AfterThrowing,异常通知,抛出异常之后执行
@Around,环绕通知,环绕着方法执行;
4.3 切面表达式的组成
主要包括:指示器,通配符,与操作符组成
例如 execution(public * com.yuanjun.myaop.service..*(..))
within(com.test.spring.aop.pointcutexp.*)等等
五、代码演示
采用springboot项目,快速搭建环境,演示,这里只演示匹配方法(execution)与匹配注解(@annotation)这两种指示器
5.1 pom文件
添加AOP的支持
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
5.2 项目目录
5.3 演示注解表达式
针对Service层增、删、改、查简单演示,重点在实现过程
自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target(ElementType.METHOD)//作用在方法上
/**
*
* @ClassName:Admin
* @Description :自定义的注解
* @author yuanjun
* @date 2018-1-5
*/
public @interface AdminOnly {
}
切面类以及通知处理
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
*
* @ClassName:MyAspect
* @Description :注解定义的切面
* @author yuanjun
* @date 2018-1-5
*/
@Aspect//注解声明切面类
@Component//交给Spring管理
public class MyAspect {
//切面表达式,拦截带有Admin注解
@Pointcut("@annotation(com.yuanjun.myaop.anno.AdminOnly)")
public void admin(){
}
//通知
@Before("admin()")
public void before(){
System.out.println("##前置通知##");
}
@After("admin()")
public void after(){
System.out.println("##后置通知##");
}
}
public class User {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
业务层接口
import com.yuanjun.myaop.bean.User;
public interface UserService {
void insertUser(User user);
User findByName(String name);
void deleteUser(int id);
void updateUser(User user);
}
业务层接口实现
import com.yuanjun.myaop.anno.AdminOnly;
import com.yuanjun.myaop.bean.User;
@Component
public class UserServiceImpl implements UserService {
@AdminOnly
public void insertUser(User user) {
System.out.println("添加用户");
}
public User findByName(String name) {
System.out.println("查询用户");
return null;
}
public void deleteUser(int id) {
System.out.println("删除用户");
}
public void updateUser(User user) {
System.out.println("修改用户");
}
}
Juit测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.yuanjun.myaop.bean.User;
import com.yuanjun.myaop.service.UserService;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyaopApplicationTests {
@Autowired
private UserService userService;
@Test
public void testInsert() {
userService.insertUser(new User());
}
@Test
public void testFind(){
userService.findByName("123");
}
}
测试结果
拦截了有@AdminOnly注解的方法
5.4 演示execution表达式的使用
参数一:修饰类型参数二:返回值的类型 参数三:拦截的包,类或者方法 参数四:方法参数 参数五:异常类型
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
*
* @ClassName:MyAspect
* @Description :注解定义的切面
* @author yuanjun
* @date 2018-1-5
*/
@Aspect//注解声明切面类
@Component//交给Spring管理
public class MyAspect {
// *表示匹配任意数量的字符 ..一般用于匹配任意数的子包或参数
@Pointcut("execution(public * com.yuanjun.myaop.service..*(..))")
public void myDemo(){
}
@Before("myDemo()")
public void before1(){
System.out.println("execution ##前置通知");
}
@After("myDemo()")
public void After1(){
System.out.println("execution ##后置通知");
}
}