SpringAOP之註解配置

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



簡單的User bean
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 ##後置通知");
	}
}










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章