AspectJ
JDK1.5級以後版本纔可使用,底層爲GDK動態代理,或CGLib代理。
/**
* AOP:【動態代理】
* 指在程序運行期間動態的將某段代碼切入到指定方法指定位置進行運行的編程方式
* 1、導入aop模塊;Spring AOP:(spring-aspects)
* 2、定義一個業務邏輯類(MathCalculator);在業務邏輯運行的時候將日誌進行打印(方法之前、方法運行結束、方法出現異常,xxx)
* 3、定義一個日誌切面類(LogAspects):切面類裏面的方法需要動態感知MathCalculator.div運行到哪裏然後執行;
* 通知方法:
* 前置通知(@Before):logStart:在目標方法(div)運行之前運行
* 後置通知(@After):logEnd:在目標方法(div)運行結束之後運行(無論方法正常結束還是異常結束)
* 返回通知(@AfterReturning):logReturn:在目標方法(div)正常返回之後運行
* 異常通知(@AfterThrowing):logException:在目標方法(div)出現異常以後運行
* 環繞通知(@Around):動態代理,手動推進目標方法運行(joinPoint.procced())
* 4、給切面類的目標方法標註何時何地運行(通知註解);
* 5、將切面類和業務邏輯類(目標方法所在類)都加入到容器中;
* 6、必須告訴Spring哪個類是切面類(給切面類上加一個註解:@Aspect)
* [7]、給配置類中加 @EnableAspectJAutoProxy 【開啓基於註解的aop模式】
* 在Spring中很多的 @EnableXXX;
* 三步:
* 1)、將業務邏輯組件和切面類都加入到容器中;告訴Spring哪個是切面類(@Aspect)
* 2)、在切面類上的每一個通知方法上標註通知註解,告訴Spring何時何地運行(切入點表達式)
* 3)、開啓基於註解的aop模式;@EnableAspectJAutoProxy
*/
@EnableAspectJAutoProxy
@Configuration
public class MyConfigOfAOP {
//業務邏輯類加入容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
//切面類加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
/**
*目標類
*/
public class MathCalculator {
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
}
/**
* 切面類
* @Aspect: 告訴Spring當前類是一個切面類
*/
@Aspect
public class LogAspects {
//抽取公共的切入點表達式
//1、本類引用
//2、其他的切面引用
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目標方法之前切入;切入點表達式(指定在哪個方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"運行。。。@Before:參數列表是:{"+Arrays.asList(args)+"}");
}
@After("com.atguigu.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"結束。。。@After");
}
//JoinPoint一定要出現在參數表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:運行結果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"異常。。。異常信息:{"+exception+"}");
}
}
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
mathCalculator.div(1, 0);
applicationContext.close();
}
Schema
在JDK1.5以前時用Schema完成AOP,底層爲JDK動態代理或CGLib代理。
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
<!-- proxy-target-class="true" 設爲true則爲CGLib代理-->
<aop:config proxy-target-class="false">
<aop:aspect ref="adviceMethod">
<!-- 定義切點 -->
<aop:pointcut expression="target(com.jun.aspect.schema.Waiter) and execution (* greetTo(..))" id="greetPoint"/>
<!-- 定義前置增強 -->
<aop:before method="beforeMethod" pointcut-ref="greetPoint"/>
<!-- 定義後置增強 -->
<aop:after method="afterMethod" pointcut-ref="greetPoint"/>
</aop:aspect>
</aop:config>
<bean id="waiter" class="com.jun.aspect.schema.WaiterImple"/>
<bean id="adviceMethod" class="com.jun.aspect.schema.AspectDemo"/>
</beans>
package com.jun.aspect.schema;
public interface Waiter {
public void greetTo(String name);
public void serveTo(String name);
}
package com.jun.aspect.schema;
public class WaiterImple implements Waiter{
public void greetTo(String name) {
System.out.println("Waiter接見你"+name);
}
public void serveTo(String name) {
System.out.println("Waiter爲你服務"+name);
}
}
package com.jun.aspect.schema;
public class AspectDemo {
public void beforeMethod() {
System.out.println("AspectJ的增強前置方法");
}
public void afterMethod() {
System.out.println("AspectJ的增強後置方法");
}
public void aroundMethod() {
System.out.println("AspectJ環繞增強");
}
}
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[]args) {
String configclass = "com/jun/aspect/schema/demo.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configclass);
Waiter wa =(Waiter) ctx.getBean("waiter");
wa.greetTo("小紅");
}
}