Spring    AspectJ

来源:互联网 发布:win10 企业版激活软件 编辑:程序博客网 时间:2024/06/02 06:40
AspectJ
.@AspectJ的风格类似纯java注解的普通java类
.Spring可以使用AspectJ来做切入点解析
.AOP的运行时仍旧是纯的Spring AOP,对AspectJ的编译器或者织入无依赖性
.对@AspectJ支持可以使用XML或java风格的配置
@Configuration
@EnableAspectJAutoProxy
public class AppConfig{}

《aop:aspectj-autoproxy/》
.确保AspectJ的aspectjweaver.jar库包括在应用程序(版本1.6.8或更高版本)的classpath中



aspect
.@AspectJ切面使用@Aspect注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用
.用@Aspect注解的类可以有方法和字段,他们也可能包括切入点(pointcut),通知(Advice)和引入(introduction)声明
.@Aspect注解是不能够通过类路径自动检测发现的,所以需要配合使用@Component注解或者在XML配置bean




pointcut
.一个切入点通过一个普通的方法定义来提供,并且切入点表达式使用@Pointcut注解,方法返回类型必须为void
.定义一个名为"anyOldTransfer",这个切入点将匹配任何名为“transfer”的方法的执行


Supported Pointcut Designators(支持的切入点指示符)
Spring <wbr> <wbr> <wbr> <wbr>AspectJ




组合pointcut
.切入点表达式可以通过&&,||和!进行组合,也可以通过名字引入切入点表达式
.通过组合,可以建立更加复杂的切入点表达式



定义良好的pointcuts
.AspectJ是编译期的AOP
.检查代码并匹配连接点与切入点的代价是昂贵的
.一个好的切入点应该包括一下几点
 -选择特定类型的连接点,如:execution,get,set,call,handler
 - 确定连接点范围,如:within,withincode
 - 匹配上下文信息,如:this,traget,@annotation





Advice定义及实例
@Component
@Aspect
public class MoocAspect{
@Before(("execution(*com.imooc.aop.aspectj.biz.*Biz.*(..))"))
public void before(){
}
}
在执行com.imooc.aop.aspectj包下以Biz结尾的类的所有方法时匹配Advice






spring-aop-aspectj.xml:
《context:component-scanbase-package="com.imooc.aop.aspectj"/》
     《aop:aspectj-autoproxy》《/aop:aspectj-autoproxy》




@Component
@Aspect
public class MoocAspect {
@Pointcut("execution(*com.imooc.aop.aspectj.biz.*Biz.*(..))")
public void pointcut() {}
@Pointcut("within(com.imooc.aop.aspectj.biz.*)")
public void bizPointcut() {}
@Before("pointcut()")
public void before() {
System.out.println("Before.");
}
}



@Service
public class MoocBiz {
public String save(String arg) {
System.out.println("MoocBiz save : " + arg);
// throw new RuntimeException(" Save failed!");
return " Save success!";
}

}



@RunWith(BlockJUnit4ClassRunner.class)
public class TestAspectJ extends UnitTestBase {
public TestAspectJ() {
super("classpath:spring-aop-aspectj.xml");
}
@Test
public void test() {
MoocBiz biz = getBean("moocBiz");
biz.save("This is test.");
}
}

测试结果:
Before.
MoocBiz save : This is test.




After returning advice
有时候需要在通用体内得到返回的实际值,可以使用@AfterReturning绑定返回值的形式
MoocAspect:
@AfterReturning(pointcut="bizPointcut()",returning="returnValue")
public void afterReturning(Object returnValue) {
System.out.println("AfterReturning : " + returnValue);
}
结果:
Before.
MoocBiz save : This is test.
AfterReturning :  Save success!




After throwing advice
有时候需要在通知体内得到返回的实际值,可以使用@AfterReturning绑定返回值的形式
MoocBiz去除异常行的注释,为return添加注释

@AfterThrowing(pointcut="pointcut()", throwing="e")
public void afterThrowing(RuntimeException e) {
System.out.println("AfterThrowing : " + e.getMessage());
}

测试结果:
Before.
MoocBiz save : This is test.
AfterThrowing :  Save failed!




After(finally) advice
最终通知必须准备处理正常和异常两种返回情况,它通常用于释放资源
@After("pointcut()")
public void after() {
System.out.println("After.");
}



测试结果:
Before.
MoocBiz save : This is test.
After.
AfterReturning :  Save success!





Around advice
.环绕通知使用@Around注解来声明,同志方法的第一个参数必须是ProceedingJoinPoint类型
.在通知内部调用ProceedingJoinPoint的proceed()方法会导致执行真正的方法,传入一个Object[]对象,数组中的值将被作为参数传递给方法


@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("Around 1.");
Object obj = pjp.proceed();
System.out.println("Around 2.");
System.out.println("Around : " + obj);
return obj;
}


测试结果:
Around 1.
Before.
MoocBiz save : This is test.
Around 2.
Around :  Save success!
After.
AfterReturning :  Save success!



给advice传递参数
Spring <wbr> <wbr> <wbr> <wbr>AspectJ

第一种:
@Before("pointcut() && args(arg)")
public void beforeWithParam(String arg) {
System.out.println("BeforeWithParam." + arg);
}


测试结果:
Around 1.
Before.
BeforeWithParam.This is test.
MoocBiz save : This is test.
Around 2.
Around :  Save success!
After.
AfterReturning :  Save success!




第二种:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MoocMethod {
String value();

}


在MoocBiz的sava方法上面添加:
@MoocMethod("MoocBiz save with MoocMethod.")



@Before("pointcut() && @annotation(moocMethod)")
public void beforeWithAnnotaion(MoocMethod moocMethod) {
System.out.println("BeforeWithAnnotation." +moocMethod.value());
}

测试结果:
Around 1.
Before.
BeforeWithAnnotation.MoocBiz save with MoocMethod.
BeforeWithParam.This is test.
MoocBiz save : This is test.
Around 2.
Around :  Save success!
After.
AfterReturning :  Save success!



Advice的参数及泛型
.Spring AOP可以处理泛型类的声明和使用方法的参数
Spring <wbr> <wbr> <wbr> <wbr>AspectJ




Advice参数名称
.通知和切入点注解有一个额外的"argNames"属性,它可以用来指定所注解的方法的参数名
Spring <wbr> <wbr> <wbr> <wbr>AspectJ

.如果第一个参数是JoinPoint,ProceedingJoinPoint,JoinPoint.StaticPart,那么可以忽略它
Spring <wbr> <wbr> <wbr> <wbr>AspectJ





Introductions
.允许一个切面声明一个通知对象实现指定接口,并且提供了一个接口实现类来代表这些对象
.Introduction使用@DeclareParents进行注解,这个注解用来定义匹配的类型拥有一个新的parent
.例如:给定一个接口UsageTracked,并且该接口拥有DefaultUsageTracked的实现,接下来的切面声明了所有的service接口的实现都实现了UsageTracked接口
Spring <wbr> <wbr> <wbr> <wbr>AspectJ




切面实例化模型
.这是一个高级主题
."perthis"切面通过指定@Aspect注解perthis子句实现
.每个独立的service对象执行时都会创建一个切面实例
.service对象的每个方法在第一次执行的时候创建切面实例,切面在service对象失效的同时失效
Spring <wbr> <wbr> <wbr> <wbr>AspectJ



0 0