AOP简介
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
简单来说,就是一个切面,可以在某一个方法的执行前或者执行后做一些操作。
比如,我之前有一个login的方法,现在要在login前做一段校验操作,在登录成功后又要做一些操作,(例如记录登录时间啦巴拉巴拉的),而你又不想改动原来的login方法,这时候你可以用到AOP,即在login的方法前和后做一些操作。
通常的做法
针对上述的需求,我们最平常的做法是。
public void login() {
beforeLogincheck(); //各种校验
//-----login主要逻辑开始----
//...
//-----login主要逻辑结束----
afterLogin(); //各种login结束后的操作
}
这样做就会修改了原先的登录方法,并且让这个方法显得臃肿。所以我们可以考虑AOP的方式,让login只关心登录逻辑代码就行,而前后的操作放在其他地方进行。
我们可以用两种方法来解决:
1、代理方式
2、spring aop
代理的方式实现
public interface LoginService {
void login();
}
public class LoginServiceImpl implements LoginService {
@Override
public void login() {
System.out.println("这里执行各种login的逻辑代码");
}
}
代理类
public class LoginProxy implements InvocationHandler {
private LoginService loginService;
public LoginProxy(LoginService loginService) {
this.loginService = loginService;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
beforeLogin(); // login之前的一些操作
Object result = method.invoke(loginService, objects); //真正的login方法
afterLogin(); // login之后的一些操作
return result;
}
public LoginService getProxy() {
return (LoginService) Proxy.newProxyInstance(loginService.getClass().getClassLoader(),
new Class[]{LoginService.class}, this);
}
private void afterLogin() {
System.out.println("在登录之后的一些操作");
}
private void beforeLogin() {
System.out.println("在登录之前的一些操作");
}
}
public class Main {
public static void main(String[] args) {
LoginProxy loginProxy = new LoginProxy(new LoginServiceImpl());
LoginService loginService = loginProxy.getProxy();
loginService.login();
}
}
AOP实现
AOP术语
class User {
add()
update()
select()
delete()
}
对着上面的代码,我们来理解以下AOP术语的概念。
-
连接点:类里面哪些方法可以被增强,这些方法称为连接点。比如add,update,select,delete,这些都是。
-
切入点:实际被真正增强的方法,称为切入点,比如上述User类下这么多方法,只有add方法增强了,那么add就是切入点。
-
通知(增强):实际增强的逻辑部分,比如在add方法前增加一段校验操作,那么这段校验就是通知。通知分为多种类型:前置通知,后置通知,环绕通知,异常通知,最终通知。
-
切面:表示一个动作,把通知应用到切入点的过程。
<!--引入AOP依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
切面类
@Aspect
@Component
public class LoginAspect {
//execution 表达式,表示com.apple.login.aop.LoginServiceImpl类下的login方法 ..表示不限制参数
@Before(value = "execution(* com.apple.login.aop.LoginServiceImpl.login(..))")
private void beforeLogin() {
System.out.println("在登录之前的一些操作");
}
@After(value = "execution(* com.apple.login.aop.LoginServiceImpl.login(..))")
private void afterLogin() {
System.out.println("在登录之后的一些操作");
}
}
@RestController
public class LoginController {
@Autowired
LoginService loginService;
@RequestMapping("/login")
public String login() {
loginService.login();
return "";
}
}
打开浏览器访问:http://localhost:8080/login
查看控制台。OK,成功。