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










猜你喜欢

转载自blog.csdn.net/shenbug/article/details/78981531