面向切面
编程范式包括面向过程、面向对象、函数式编程、事件驱动编程和面向切面编程。
面向切面(AOP)编程是对面向对象(OOP)的补充,解决某一类特定问题。
面向切面主要要解决的问题是DRY(don’t repeat yourself)和SOC(separation of concerns)关注点分离。
关注点分离既包括横向分离(展示层、服务层、持久层),又包括垂直分离(不同的模块)。面向切面要实现的就是把功能性需求从非功能性需求中分离出来。
权限控制,缓存控制,事务控制,日志监控,异常处理都是AOP可以发挥的地方。
##商品管理员例子
需求为只有管理员可以操作商品。
商品的模型如下所示:
public class Product {
private Long id;
private String name;
// ...
}
控制的服务为
public class ProductService {
public void insert(Product product) {
System.out.println("insert success");
}
public void delete(Long id) {
System.out.println("delete success");
}
}
权限校验的类为
public class AuthService {
public void checkAccess() {
String user = xx.get();
if (!"admin".equals(user)) {
throw new RuntimeException("...");
}
}
}
如果我们将鉴权操作增加到操作商品中间,就会出现这样的硬编码
public class ProductService {
@Autowired
AuthService authService;
public void insert(Product product) {
authService.checkAccess();
System.out.println("insert success");
}
public void delete(Long id) {
authService.checkAccess();
System.out.println("delete success");
}
}
这时可以定义一个切面
@Aspect
@Component
Public class SecurityAspect {
@Autowired
AuthService authService;
// 声明annotation(注解)
@Pointcut("annotation(AdminOnly)")
public void adminOnly() {
}
@Before("adminOnly()")
public void check() {
authService.checkAccess();
}
}
这时就可以在服务层通过注解方式来引入,在方法之前进行了拦截
public class ProductService {
@AdminOnly
public void insert(Product product) {
System.out.println("insert success");
}
@AdminOnly
public void delete(Long id) {
System.out.println("delete success");
}
}
具体使用
Spring AOP可以通过xml方式或者注解方式进行配置(对AOP进行声明)。