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,成功。