您的位置:首页 > 编程语言 > Java开发

使用Spring进行面向方面编程

2016-08-11 17:18 459 查看

使用Spring进行面向方面编程

1. 在Spring中开始使用AOP

记录方法执行

引入依赖

spring-aop

spring-core

spring-beans

spring-context

aspectjweaver

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>


创建执行通知的类,实现MethodBeforeAdvice,AfterReturningAdvice接口

public class MethodTimeAop implements MethodBeforeAdvice,AfterReturningAdvice {
long time=0;
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
time=System.currentTimeMillis()-time;
System.out.println("执行方法"+o1.getClass().getCanonicalName()+"类 "+method.getName()+"耗时 "+time);
time=0;
}

@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
time=System.currentTimeMillis();
}
}


创建Spring配置文件,配置执行执行通知的Bean 切入点 通知

<context:component-scan base-package="org.pikachu"/>
<context:annotation-config></context:annotation-config>
<bean class="org.pikachu.MethodTimeAop" id="methodTimeAop">

</bean>

<aop:config>
<aop:pointcut id="methodTimePointcut" expression="execution(public * *(..))"/>
<aop:advisor advice-ref="methodTimeAop" pointcut-ref="methodTimePointcut"/>
</aop:config>


创建两个类,分别编写一个方法 使用类级别@Component

在main函数中进行测试

2. 熟悉通知的类型

Before

After Returning

After Throwing

After(Finally)

Around

public class MehtodAop implements MethodBeforeAdvice,
AfterReturningAdvice,
ThrowsAdvice{
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
String methodName=method.getName();
String className=o.getClass().getName();
System.out.println("Before "+className+"类 "+methodName+"方法");
}

@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
String methodName=method.getName();
String className=o1.getClass().getName();
System.out.println("After Returning "+className+"类 "+methodName+"方法");

}
public void afterThrowing(Method method,Object[] args,Object target,Exception ex){

String methodName=method.getName();
String className=target.getClass().getName();
System.out.println("afterThrowing "+className+"类 "+methodName+"方法");
}
public void afterfinally(JoinPoint joinpoint){
String methodName=joinpoint.getSignature().getClass().getCanonicalName();
String className=joinpoint.getTarget().getClass().getCanonicalName();
System.out.println("after finally "+className+"类 "+methodName+"方法");
}
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName=joinPoint.getSignature().getName();
String className=joinPoint.getTarget().getClass().getName();
System.out.println("around before "+className+"类 "+methodName+"方法");
joinPoint.proceed();
System.out.println("around after "+className+"类 "+methodName+"方法");
}
}


<context:component-scan base-package="org.pikachu"/>
<context:annotation-config></context:annotation-config>
<bean class="org.pikachu.MehtodAop" id="mehtodAop">

</bean>
<aop:config>
<aop:pointcut id="aopPointcut" expression="execution(public * *(..))"/>
<aop:advisor advice-ref="mehtodAop" pointcut-ref="aopPointcut"/>
<aop:aspect ref="mehtodAop">
<aop:after method="afterfinally" pointcut-ref="aopPointcut"/>
<aop:around method="around" pointcut-ref="aopPointcut"/>
</aop:aspect>
</aop:config>


顺序

Before

around before

after finally

around after

After Returning

3. 定义切入点指示符

within()

execution(.*(parameters))

bean(*Service)

@annotation(org.pikachu.MarkerMethodAnnotation)

@within(org.pikachu.MarkerMethodAnnotation)

This(org.pikachu.MarkerMethodAnnotation)

通配符定义
..匹配方法定义中的任何数量的参数,匹配类定义中任何数量的包
+匹配给定类的任何子类
*匹配任何数量的字符

4. 利用注解的强大功能

@Before

@PointCut

@After

@AfterReturning

@AfterThrowing

@Aspect

@Around

@DeclareParents

@Component
@Aspect
public class MethodAop {
@Pointcut("execution(public * *(..))")
public void anyPublicMethod(){

}
@Pointcut("@annotation(org.pikachu.MarkerAnnotation)")
public void annotationWithMarkerAnnotation(){

}
@Before("anyPublicMethod()")
public void before(JoinPoint joinPoint){
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("@Before "+className+"类 "+methodName+"方法");
}
@Before(value = "anyPublicMethod() && args(param)")
public void before(JoinPoint joinPoint,String param){
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("@Before "+className+"类 "+methodName+"方法" +" 带有参数 "+param);

}
@After("anyPublicMethod() && annotationWithMarkerAnnotation())")
public void after(JoinPoint joinPoint){
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("@After "+className+"类 "+methodName+"方法"+" 带有注解@MarkAnnotation");

}
@AfterReturning(value = "anyPublicMethod() ",returning = "returnParam")
public void afterReturning(JoinPoint joinPoint, String returnParam){
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("@AfterReturning "+className+"类 "+methodName+"方法"+" 返回值 "+returnParam);

}
@AfterReturning("anyPublicMethod()")
public void afterReturning(JoinPoint joinPoint){
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("@AfterReturning "+className+"类 "+methodName+"方法");

}
@AfterThrowing(value = "within(org.pikachu.MethodTest)",throwing = <
dd66
span class="hljs-string">"t")
public void afterThrowing(JoinPoint joinPoint,Throwable t){
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("@AfterThrowing "+className+"类 "+methodName+"方法"+" 异常"+t.getMessage());

}
@Around("anyPublicMethod()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("@Around before "+className+"类 "+methodName+"方法");
joinPoint.proceed();
System.out.println("@Around after "+className+"类 "+methodName+"方法");

}
}


@Component
@Aspect
public class GreekMythologyIntroducer {
@DeclareParents(value = "org.pikachu.declareParents.Pegasus+",defaultImpl = Bird.class)
public static IBird iBird;
}


5. 将ApectJ和Spring融合在一起

使用ApectJ记录方法的执行时间

<context:component-scan base-package="org.pikachu"/>
<context:annotation-config></context:annotation-config>

<aop:aspectj-autoproxy>

</aop:aspectj-autoproxy>


6. 使用注解配置Spring AOP

使用@Configuration

使用@ComponentScan 配置basePackages

使用@EnableAspectJAutoProxy 启用AspectJ注解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: