Spring框架-AOP核心
Spring AOP
AOP (Aspect Oriented Programming) 面向切面編程
OOP(Object Oriented Programming)面向對象編程,用對象的思想來完善程序
AOP是的OOP的一個補充,是在另外一個維度上抽象出的對象。
具體是指程序運行時動態的將非業務代碼切入到業務代碼中,從而實現程序的解耦合,將非業務抽象成一個對象,對對象編程就是面向對象編程。
在同樣的地方有相同的方法抽象成一個切面----代碼A切面對象。
AOP的優點:
可以降低模塊之間的耦合性
提高代碼的復用性
集中管理代碼的維護性
集中管理代碼的非義務代碼,便于維護
業務代碼不受非業務代碼的影響,邏輯更加清晰
理解AOP
創建接口的計算器類
java
package com.southwind.aop;
public interface Cal {
public int add(int num1,int num2);
public int sub(int num1,int num2);
public int mul(int num1,int num2);
public int div(int num1,int num2);
}
2.實現類:
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
}
@Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
}
@Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
}
@Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}
3.日志打印:
在每個方法開始的位置輸出參數的信息
在每個方法的結束的位置輸出結果信息
對于計算器而言,加減乘除是業務代碼,日志是非業務代碼。
AOP如何實現?:
使用動態代理
代理首先具備CaLImpl的基礎功能,然后在這個基礎上擴展日志功能
刪除CalImpl方法中的打印日志的代碼,只保留業務代碼
創建MyinvocationHandler類,實現IvocationHandler接口,生成動態代理類
動態代理類要動態生成。
ClassLoader用來將動態的類加載到虛擬機(JVM)中。
Proxy.newProxyInstance(類加載器《object.getClass.getClassLoder》,委托對象的接口《object.getClass().getInterfaces()》,this);
動態創建代理類---方到實體類里面。
底層原理
1.接口:
```java
package com.southwind.aop;
public interface Cal {
public int add(int num1,int num2);
public int sub(int num1,int num2);
public int mul(int num1,int num2);
public int div(int num1,int num2);
}
2.代理對象:
package com.southwind.aop;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class MyinvocationHandler implements InvocationHandler {
//委托對象
private Object object=null;
//返回代理對象
public Object bind(Object object){
this.object=object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),this);
}
?
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//實現業務代碼和非業務代碼調用
System.out.println(method.getName()+"方法的參數是:"+ Arrays.toString(args));
Object result=method.invoke(this.object,args);
System.out.println(method.getName()+"方法的參數是:"+ result);
return result;
}
}
```
3.實現類;
```java
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
}
@Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
}
@Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
}
@Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}
4.測試類:
?
?```java
package com.southwind.test;
import com.southwind.aop.Cal;
import com.southwind.aop.MyinvocationHandler;
import com.southwind.aop.impl.CalImpl;
public class Test10 {
public static void main(String[] args) {
//實例化委托對象
Cal cal = new CalImpl();
// cal.add(10,3);
// cal.div(10,3);
// cal.mul(10,3);
// cal.sub(10,3);
// 獲取代理對象
MyinvocationHandler myinvocationHandler= new MyinvocationHandler();
Cal proxy=(Cal)myinvocationHandler.bind(cal);
proxy.add(10,3);
}
}
上述代碼的動態機制實現了業務代碼和非業務代碼的解耦合,這是SpringAOP的底層實現機制,不要這么復雜,有更好的方式。
Spring AOP的開發步驟:
1.創建切面類:
package com.southwind.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.lang.reflect.Array;
import java.util.Arrays;
@Component
@Aspect
public class LogAspect {
@Before("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void before(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
String args= Arrays.toString((joinPoint.getArgs()));
System.out.println(name+"方法的參數是"+args);
}
@After("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void after(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
System.out.println(name+"方法執行完畢");
}
@AfterReturning(value = "execution(public int com.southwind.aop.impl.CalImpl.*(..))",returning = "result")
public void afterReturn(JoinPoint joinPoint,Object result){
String name=joinPoint.getSignature().getName();
System.out.println(name+"方法執行完畢"+"結果是:"+result);
}
@AfterThrowing(value = "execution(public int com.southwind.aop.impl.CalImpl.*(..))",throwing = "ex")
public void afterTrowing(JoinPoint joinPoint,Exception ex){
String name= joinPoint.getSignature().getName();
System.out.println(name+"方法拋出異常"+ex);
}
}
2.委托類加上@Component
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
import org.springframework.stereotype.Component;
@Component
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
}
@Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
}
@Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
}
@Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}
3.配置spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 掃包-->
<context:component-scan base-package="com.southwind.aop"></context:component-scan>
<!-- 自動代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
3測試類:
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-aop.xml");
Cal cal = (Cal)applicationContext.getBean("a");
System.out.println(cal.add(10,3));
}
}
@Component 將切面類加載到IoC容器中
@Aspect 表示類是一個切面類
@Before 表示方法執行的時機,execution表示的是切入點是CallImpl中執行add方法之前執行日志方法
@AfterReturning,表示方法的執行時機是再業務方法返回結果:returning是將返回的業務代碼的返回的形參
@AfterThrowing:表示方法執行是拋出的異常,throwing表示拋出的異常的處理形參
aop:aspectj-autoproxy ,Spring IoC容器會結合動態代理對象自動的生成代理對象,AOP底層就是通過動態代理對象來實現的。
AOP的概念:
切面對象;根據切面抽象出來的對象,Callmpl所有的方法中需要加入日志的部分,抽象成一個切面對象
通知:切面對象具體執行的代碼,即具體的非業務代碼,LoggerAspect對象打印日志的代碼
目標;被橫切的對象,即CallImpl將通知加入其中。
代理:切面對象、通知、目標混合之后的結果,即時我門使用JDK動態代理的機制創建對象
連接點;需要被橫切的位置,即要通知要插入業務代碼的具體位置
總結
以上是生活随笔為你收集整理的Spring框架-AOP核心的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: goalng 将字符串转化成整数后取余
- 下一篇: 201671030111 李蓉 实验十四