spring中aop中的两种方式
第一种方式:注解的方式
第一步:创建aspect类
package com.liusir.aop.xml;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
public class longingaspect {
public void declareJoinPointExpression() {}
public void BeforeMethod(JoinPoint joinpoint) {
String methodname = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println("The method" + methodname + "begins with" + args);
}
public void afterMethod(JoinPoint joinpoint) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end..");
}
public void afterReturnMethod(JoinPoint joinpoint, Object result) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + result);
}
public void throwingMethod(JoinPoint joinpoint, Exception ex) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + ex);
}
}
第二步:配置spring.xml文件
<!-- aop 自动切面编程 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
注解的方式文件的配置很简单。
第三步:加入相应的注解
一共有五种注解:@Before @After @AfterReturning @AfterThrowing @Round
注意:再注解当中需要备好 execution
下面是将上面的aspect代码进行完善
package com.liusir.aop;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class longingaspect {
//定义一个方法,用于表明切入点的表达式,一般的,该方法种不再添加任何代码
//使用@Pointcut 来表明切入点的表达式
//后面的其他通知直接使用方法名来引用当前的切入点的表达式
@Pointcut("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
public void declareJoinPointExpression() {}
//用order来指定优先级, order值越小,优先级越高。
@Order
// 在目标方法执行前进行通知
@Before("declareJoinPointExpression()")
public void BeforeMethod(JoinPoint joinpoint) {
String methodname = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println("The method" + methodname + "begins with" + args);
}
// 在目标方法执行后进行通知,(无论是否发生异常都会通知)
// 但是还不能访问结果
@After("declareJoinPointExpression()")
public void afterMethod(JoinPoint joinpoint) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end..");
}
// 在方法正常结束受执行的代码
// 后置返回通知会有返回结果
@AfterReturning(value = "declareJoinPointExpression()", returning = "result")
public void afterReturnMethod(JoinPoint joinpoint, Object result) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + result);
}
// 在目标受到异常时执行的代码
// 可以访问异常对象,且可以指定出现特定异常时在执行通知的代码。
@AfterThrowing(value = "declareJoinPointExpression()", throwing = "ex")
public void throwingMethod(JoinPoint joinpoint, Exception ex) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + ex);
}
// 环绕通知需要携带ProceedingJoinPoint这个
// 环绕通知类似于动态代理的全过程:ProceedingJoinpoint的类型参数 可以指定是否执行目标方法
// 且必须有返回值,返回值即为目标方法的返回值
/*
@Around("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
public Object Around(ProceedingJoinPoint joinpoint) {
Object object = null;
try {
//前置通知
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "starts"+Arrays.asList(joinpoint.getArgs()) );
//执行方法
object = joinpoint.proceed();
//后置通知返回值
System.out.println("The method" + methodname + "end.."+object);
} catch (Throwable e) {
System.out.println("The method.."+e);
}
//后置通知。。
System.out.println("The method end....");
return object;
}*/
}
注意: 里面有 点需要说:
第一点:切入点的表达式
@Pointcut(“execution(int com.liusir.aop.ArithmeticDao.*(int, int))”)
public void declareJoinPointExpression() {}
:一般这个方法内部是需要添加任何代码,只是一种标识作用。
:@Pointcut来标识
:例子:普通和使用表达式的差别
:切入点表达式:
@AfterReturning(value = "declareJoinPointExpression()", returning = "result")
public void afterReturnMethod(JoinPoint joinpoint, Object result) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + result);
}
:普通:
@AfterReturning(value ="execution(int com.liusir.aop.ArithmeticDao.*(int, int))" , returning = "result")
public void afterReturnMethod(JoinPoint joinpoint, Object result) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + result);
}
第二点:@AfterReturning @AfterThrowing
注意AfterReturning注解里的内容,多一个returning,returning=“result”
是方法中的参数的名:public void afterreturnTest(JoinPoint joinpoint,Object result);
注意AfterThrowing注解里的内容,多了一个throwing,throwing=“ex”
是方法中异常的参数名:public void throwingMethod(JoinPoint joinpoint, Exception ex);
第三点:@around:
可以理解为将前面的四个注解组合起来,完全像动态代理的处理方式。
第四点:@Aspect
第五点:关于方法标签
如果大家想测试:下面将全部的代码
package com.liusir.aop;
public interface ArithmeticDao {
public int add(int i,int j);
public int div(int i,int j);
}
package com.liusir.aop;
import org.springframework.stereotype.Component;
@Component
public class ArithmeticImpl implements ArithmeticDao{
@Override
public int add(int i,int j) {
int result=i+j;
return result;
}
@Override
public int div(int i,int j) {
int result=i/j;
return result;
}
}
package com.liusir.aop;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class longingaspect {
//定义一个方法,用于表明切入点的表达式,一般的,该方法种不再添加任何代码
//使用@Pointcut 来表明切入点的表达式
//后面的其他通知直接使用方法名来引用当前的切入点的表达式
@Pointcut("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
public void declareJoinPointExpression() {}
//用order来指定优先级, order值越小,优先级越高。
@Order
// 在目标方法执行前进行通知
@Before("declareJoinPointExpression()")
public void BeforeMethod(JoinPoint joinpoint) {
String methodname = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println("The method" + methodname + "begins with" + args);
}
// 在目标方法执行后进行通知,(无论是否发生异常都会通知)
// 但是还不能访问结果
@After("declareJoinPointExpression()")
public void afterMethod(JoinPoint joinpoint) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end..");
}
// 在方法正常结束受执行的代码
// 后置返回通知会有返回结果
@AfterReturning(value = "declareJoinPointExpression()", returning = "result")
public void afterReturnMethod(JoinPoint joinpoint, Object result) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + result);
}
// 在目标受到异常时执行的代码
// 可以访问异常对象,且可以指定出现特定异常时在执行通知的代码。
@AfterThrowing(value = "declareJoinPointExpression()", throwing = "ex")
public void throwingMethod(JoinPoint joinpoint, Exception ex) {
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "end.." + ex);
}
// 环绕通知需要携带ProceedingJoinPoint这个
// 环绕通知类似于动态代理的全过程:ProceedingJoinpoint的类型参数 可以指定是否执行目标方法
// 且必须有返回值,返回值即为目标方法的返回值
/*
@Around("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
public Object Around(ProceedingJoinPoint joinpoint) {
Object object = null;
try {
//前置通知
String methodname = joinpoint.getSignature().getName();
System.out.println("The method" + methodname + "starts"+Arrays.asList(joinpoint.getArgs()) );
//执行方法
object = joinpoint.proceed();
//后置通知返回值
System.out.println("The method" + methodname + "end.."+object);
} catch (Throwable e) {
System.out.println("The method.."+e);
}
//后置通知。。
System.out.println("The method end....");
return object;
}*/
}
package com.liusir.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class main {
public static void main(String[] args) {
ApplicationContext ctx=null;
ctx = new ClassPathXmlApplicationContext("aop.xml");
ArithmeticDao arithmeticDao=ctx.getBean(ArithmeticDao.class);
int add = arithmeticDao.add(2, 4);
int div =arithmeticDao.div(2, 1);
System.out.println(add);
}
}
配置文件:
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<context:component-scan base-package="com.liusir.aop"></context:component-scan>
<!-- aop 自动切面编程 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
第二种方式:用spring.xml文件来配置
注意 :一下代码是上面代码将注解的部分全部删除,然后可以直接进行测试
spring.xml中的细节信息
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<bean id="Arithmeticlmpl"
class="com.liusir.aop.xml.ArithmeticImpl">
</bean>
<!-- 配置切面的bean -->
<bean id="loggingaspect" class="com.liusir.aop.xml.longingaspect">
</bean>
<!-- 配置aop -->
<aop:config>
<!-- 配置切面表达式 -->
<!-- 来定位那个类中方法信息。 -->
<aop:pointcut
expression="execution(int com.liusir.aop.xml.ArithmeticDao.*(int, int))"
id="pointcut" />
<!-- 切面表达式及通知 -->
<aop:aspect ref="loggingaspect">
<aop:before method="BeforeMethod" pointcut-ref="pointcut" />
<aop:after-returning method="afterReturnMethod"
pointcut-ref="pointcut" returning="result"/>
<aop:after method="afterMethod" pointcut-ref="pointcut" />
<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut" throwing="ex"/>
</aop:aspect>
</aop:config>
</beans>
注意:第一点:
声明切面的代码实例
<!-- 配置切面的bean -->
<bean id="loggingaspect" class="com.liusir.aop.xml.longingaspect">
</bean>
声明切入点:
<!-- 配置切面表达式 -->
<!-- 来定位那个类中方法信息。 -->
<aop:pointcut
expression="execution(int com.liusir.aop.xml.ArithmeticDao.*(int, int))"
id="pointcut" />
声明通知实例
<!-- 切面表达式及通知 -->
<aop:aspect ref="loggingaspect">
<aop:before method="BeforeMethod" pointcut-ref="pointcut" />
<aop:after-returning method="afterReturnMethod"
pointcut-ref="pointcut" returning="result"/>
<aop:after method="afterMethod" pointcut-ref="pointcut" />
<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut" throwing="ex"/>
</aop:aspect>