IOC和AOP是Spring中的兩個核心的概念,簡單介紹一下我的理解:
IOC:控制反轉,就是將以前由我們自己手動創建物件的過程交給了Spring,Spring幫助我們生產物件、管理物件、管理物件和物件之間的依賴關係。降低了程式碼的耦合度,方便我們後期對專案做維護。舉個通俗一點的例子:
正常情況下,我們在家,餓了,自己煮飯。
使用IOC情況下,我們在家,餓了,打電話給商家,飯送過來。
IOC就相當於商家,做菜就等於創建物件。
也就是說正常情況下,當一個類別需要呼叫其他類別的方法時,我們手動透過new、工廠或其他方式建立物件。
使用IOC情況下,我們只需要注入物件即可。
AOP:面向切面(方便)編程,可以對某一類物件進行監督和控制,在調用這類物件方法的前後去調用指定的程式碼,從而對一個方法進行擴展,從而達到增強模組功能的效果。舉個通俗一點的例子:
正常情況下,直接吃飯。
使用AOP情況下,有個保母注意著,吃飯前幫忙洗手,吃飯後幫忙收拾碗筷。
AOP就相當於保姆,吃飯就等於帶調用具體的方法。
也就是說,當我們想要對方法進行補充時,並不會去直接修改方法,而是透過AOP去補充。當我們不想補充或需要更換補充的時候,直接操作AOP即可。
1、Pointcut: 切點,用來定義哪個方法會被攔截,例如execution(* cn.springcamp.springaop.service..(…))
2、Advice: 攔截到方法後面要執行的動作
3、Aspect: 切面,把Pointcut和Advice組合在一起形成一個切面
4、Join Point: 在執行時Pointcut的一個實例
#4、Weaver: 實作AOP的框架,例如AspectJ 或Spring AOP
<!--aop--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
啟動類別加上@EnableAspectJAutoProxy註解,可以省略。因為在AOP的預設配置屬性中,spring.aop.auto屬性預設是開啟的。
也不需要再引入AspectJ依賴了。
切面類別程式碼:
package com.example.myblog.test; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect public class AOPTest { //定义切入点 @Pointcut("execution(public * com.example.myblog.test.AOPTestClient.*(..))") public void aspectTest(){} //前置通知,切入点执行之前执行 @Before("aspectTest()") public void doBefore(JoinPoint joinPoint){ System.out.println("前置通知"); } //后置通知,切入点执行之后执行 @After("aspectTest()") public void doAfter(JoinPoint joinPoint){ System.out.println("后置通知"); } //最终通知,,切入点执行之后执行 @AfterReturning("aspectTest()") public void doAfterReturning(JoinPoint joinPoint){ System.out.println("最终通知"); } //异常通知,切入点抛出异常执行 @AfterThrowing("aspectTest()") public void deAfterThrowing(JoinPoint joinPoint){ System.out.println("异常通知"); } //环绕通知,切入点执行前、后执行 @Around("aspectTest()") public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("未执行"); Object result = joinPoint.proceed(); System.out.println("已执行"); //返回结果 return result; } }
切點類別程式碼:
package com.example.myblog.test; import org.springframework.stereotype.Component; @Component public class AOPTestClient { public void test(){ System.out.println("正在测试AOP"); } }
測試類別程式碼:
package com.example.myblog; import com.example.myblog.test.*; 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.SpringJUnit4ClassRunner; @SpringBootTest @RunWith(SpringJUnit4ClassRunner.class) public class MyblogApplicationTests { @Autowired private AOPTestClient aopTestClient; @Test public void testAOP(){ aopTestClient.test(); } }
測試結果:
自訂註解程式碼:
package com.example.myblog.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //表示次注解可以标注在类和方法上 @Target({ElementType.METHOD, ElementType.TYPE}) //运行时生效 @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { //定义一个变量,可以接受参数 String desc() default " "; }
切面類別程式碼:
package com.example.myblog.test; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect public class AOPAnnotationTest { //定义切入点 @Pointcut("@annotation(com.example.myblog.test.MyAnnotation)") public void aspectTest(){} //前置通知,切入点执行之前执行 @Before("aspectTest()") public void doBefore(JoinPoint joinPoint){ System.out.println("前置通知"); } //后置通知,切入点执行之后执行 @After("aspectTest()") public void doAfter(JoinPoint joinPoint){ System.out.println("后置通知"); } //最终通知,,切入点执行之后执行 @AfterReturning("aspectTest()") public void doAfterReturning(JoinPoint joinPoint){ System.out.println("最终通知"); } //异常通知,切入点抛出异常执行 @AfterThrowing("aspectTest()") public void deAfterThrowing(JoinPoint joinPoint){ System.out.println("异常通知"); } //环绕通知,切入点执行前、后执行 @Around("aspectTest()") public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("未执行"); Object result = joinPoint.proceed(); System.out.println("已执行"); //返回结果 return result; } }
切點類別程式碼:
package com.example.myblog.test; import org.springframework.stereotype.Component; @Component public class AOPAnnotationTestClient { @MyAnnotation public void test(){ System.out.println("正在测试AOP"); } }
測試類別程式碼:
@Test public void testAOPAnnotation(){ aopAnnotationTestClient.test(); }
測試結果:
以上是SpringBoot專案怎麼使用aop的詳細內容。更多資訊請關注PHP中文網其他相關文章!