aop的目標(biāo):
- 方法增強(qiáng),構(gòu)造器增強(qiáng)吭狡,屬性增強(qiáng)
- 動(dòng)態(tài)的向”對(duì)象“添加方法(Introduction)
核心概念:
- 技術(shù)本質(zhì):運(yùn)行時(shí)的"動(dòng)態(tài)字節(jié)碼生成"丙号,使用JDK的Proxy和CGLIB技術(shù)
- 目前可以完成兩大功能:方法調(diào)用代理和方法引入侨核。
- 基本名詞:Aspect,Advice,JoinPoint,Pointcut,Introduction,Weaving
- weaving的基本方式 :編譯期(AspectJ),類加載期(AspectJ5)贷帮,運(yùn)行期(Spring)
Spring對(duì)AOP的支持:
- 經(jīng)典方式(不推薦):
基于org.aopalliance.aop.Advice 及ProxyFactoryBean
,需要大量的配置及非pojo類的侵入式設(shè)計(jì) - pojo 切面
基于<aop: >
方式柒瓣,不需要引入接口儒搭,但只能基于xml方式 - 使用AspectJ的注解(需要引入AspectJweaver包)
該方法只是使用了AspectJ的注解,來(lái)完成pojo切面的注解方式 - 使用AspectJ的切面
利用強(qiáng)大的AspectJ框架的切面芙贫,完成構(gòu)造器及屬性攔截搂鲫。
Aspect、Advice屹培、Pointcut的定義默穴,設(shè)定Joinpoint及Weaving
- 類級(jí)別上
@Aspect
- 方法級(jí)別定義Joinpoint
@Bfore,@After,@AfterThrowing,@AfterReturning,@Around
- 在joinpoint中怔檩,定義pointcut:
@Before("execution(* package.ClassName.method(args))")
- (選項(xiàng):pointcut的復(fù)用):
@Pointcut("execution(* ...)") method(){};
此時(shí),@Before("method()") - 注入容器:@Component或<bean class="..">
- 啟動(dòng)自動(dòng)代理:@EnableAspectJAutoProxy或<aop:asepect-autoproxy>
處理目標(biāo)中的參數(shù)
- 使用環(huán)繞通知中的參數(shù)獲取
ProceedingJoinPoint
- 利用AspectJ指示器:args()及this()
- 使用:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
//單獨(dú)定義pointcut的兩種方式
@Pointcut(value = "execution(* cn.johnyu.service.WorkService.work(int))&&args(arg)&&this(target)")
public void pointcut1(int arg,Object target){};
public final String pointcut2="execution(* cn.johnyu.service.WorkService.work(int))&&args(arg)&&this(target)";
//定義Joinpoint及使用pointcut
@Before("pointcut1(arg,target)")
//@Before(pointcut2)
// @Before(value = "execution(* cn.johnyu.service.WorkService.work(int))&&args(arg)&&this(target)")
public void logBefore(int arg,Object target){
//arg是target方法中的參數(shù)蓄诽,target是當(dāng)前被代理對(duì)象
}
}
為“對(duì)象”加入新方法
Java為靜態(tài)語(yǔ)言薛训,此項(xiàng)工作并不提供原生的支持
只能通過(guò)操作字節(jié)碼的方案完成此項(xiàng)工作
Spring利用AspectJ的注解,在運(yùn)行期完成了此項(xiàng)工作仑氛。
新增加的接口及功能實(shí)現(xiàn):
@Component
public class AttachFunctionImpl implements AttachFunction{
@Override
public void attach() {
System.out.println("attach....");
}
}
- 使用“Introductor”類
@Aspect
@Component
public class AttachIntroducer {
// "+"表明乙埃,代理的目標(biāo)為接口所有的實(shí)現(xiàn)類
@DeclareParents(value = "cn.johnyu.service.WorkService+",defaultImpl = AttachFunctionImpl.class)
public static AttachFunction attachFunction;
}
- 測(cè)試使用:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class AppTest {
@Autowired private WorkService workService;
@Test
public void test1(){
workService.work(2);
AttachFunction a=(AttachFunction)workService;
a.attach();
}
}