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 ##後置通知");
}
}