aop实现初步
applicationContext.xml配置内容
<context:annotation-config /> <context:component-scan base-package="cn.mldn" /> <!-- 如果要想让切面控制有效,那么必须将此类的对象交由Spring进行管理 --> <bean id="serviceProxy" class="cn.mldn.aop.ServiceProxy"/> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 要求进入AOP的配置,重点配置切入点,以及确定切入的处理方法 --> <aop:config> <!-- execution(修饰符匹配? 返回值类型匹配 操作类型匹配? 名称匹配(参数匹配) 抛出异常匹配 ) : 主要是用于定义切入点的执行语法 --> <!-- 本次操作里面没有编写修饰符 ,如果要编写可以使用 public private编写,可以出现0次或一次 如:"execution(public * cn.mldn..*.*(..))"--> <!-- "*" : 表示返回值,即支持所有类型的返回值 --> <!-- cn.mldn.. : 描述的是包名称的匹配 ,如果是 “..” 表示任意的子包下控制 --> <!-- *.* : 描述的是“类.方法” ,*。* 表示所有的类与所有的方法 --> <!-- .. : 描述的是参数 , “..” 表示任意的参数 --> <aop:pointcut expression="execution(* cn.mldn.service..*.*(..))" id="pointCut"/> <!-- 设置切入点 --> <aop:aspect ref="serviceProxy"> <!-- 进行切面的配置 , 如果是切面控制应该有一个控制的类 --> <!-- 不同的切面处理操作可以使用同一个切入点,或者每一个操作来定义属于自己的切入点 --> <aop:before method="beforeMethod" pointcut-ref="pointCut"/> <aop:after method="afterMethod" pointcut-ref="pointCut"/> </aop:aspect> </aop:config>
Service
package cn.mldn.service.impl; import org.springframework.stereotype.Service; import cn.mldn.service.IMemberService; @Service public class MemberServiceImpl implements IMemberService { @Override public boolean delete(String mid) throws Exception { System.out.println("[MemberService] 数据删除处理"); return false; } }
package cn.mldn.service;
public interface IMemberService {
public boolean delete(String mid) throws Exception ;
}
proxy
package cn.mldn.aop; public class ServiceProxy { public void beforeMethod() { System.out.println("###### [ServiceProxy] public void beforeMethod(){}"); } public void afterMethod() { System.out.println("###### [ServiceProxy] public void afterMethod(){}"); } }
test
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); IMemberService ms = ctx.getBean("memberServiceImpl" ,MemberServiceImpl.class) ; ms.delete("123");
result
###### [ServiceProxy] public void beforeMethod(){} [MemberService] 数据删除处理 ###### [ServiceProxy] public void afterMethod(){}
切面函数配置参数
public class ServiceProxy { public void beforeMethod(Object obj) { System.out.println("###### [ServiceProxy] public void beforeMethod(){} ,参数内容:"+obj); } public void afterMethod() { System.out.println("###### [ServiceProxy] public void afterMethod(){}"); } }
<aop:pointcut expression="execution(* cn.mldn.service..*.*(..)) and args(id)" id="pointCut"/> <aop:aspect ref="serviceProxy"> <!-- 上面的args里面的id与arg-names的id是一至的 --> <aop:before method="beforeMethod" pointcut-ref="pointCut" arg-names="id"/> <aop:after method="afterMethod" pointcut="execution(* cn.mldn.service..*.*(..))"/> </aop:aspect>
其他配置
<aop:aspect ref="serviceProxy"> <!-- 进行切面的配置 , 如果是切面控制应该有一个控制的类 --> <!-- 不同的切面处理操作可以使用同一个切入点,或者每一个操作来定义属于自己的切入点 --> <aop:before method="beforeMethod" pointcut-ref="pointCut" arg-names="id"/> <aop:after method="afterMethod" pointcut="execution(* cn.mldn.service..*.*(..))"/> <!-- 返回值切面 v 只是个标记,随便写 ,只是接收,不能更改--> <aop:after-returning method="returnMethod" pointcut="execution(* cn.mldn.service..*.*(..))" returning="v" arg-names="v"/> <!-- 针对异常进行处理, --> <aop:after-throwing method="throwMethod" pointcut="execution(* cn.mldn.service..*.*(..))" throwing="e" arg-names="e"/>
<!-- 环绕通知的配置 -->
<aop:around method="aroundMethod" pointcut="execution(* cn.mldn.service..*.*(..))"/>
</aop:aspect>
package cn.mldn.aop; public class ServiceProxy { public void beforeMethod(Object obj) { System.out.println("###### [ServiceProxy] public void beforeMethod(){} ,参数内容:"+obj); } public void afterMethod() { System.out.println("###### [ServiceProxy] public void afterMethod(){}"); } public void returnMethod(Object val) { //处理返回值 System.out.println("###### [ServiceProxy] public void returnMethod(){} ,返回值:" + val); } public void throwMethod(Exception e) { // 对异常进行处理 System.out.println("###### [ServiceProxy] public void throwMethod(){} 异常信息:" + e ); }
public Object aroundMethod(ProceedingJoinPoint point) throws Throwable { //调用具体的执行方法
System.out.println("@@@@@@ aroundMethod() - before 参数:" + new Arrays().toString(point.getArgs()));
//此时可以正对于参数接收后处理后再传递的操作
Object obj = point.proceed(new Object [] {"abc"});
System.out.println("@@@@@@ aroundMethod() - after 返回结果:" + obj);
return true ; //还可以不按照结果返回数据
}
}
aop annotation
package cn.mldn.aop; import org.apache.catalina.tribes.util.Arrays; 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.springframework.stereotype.Component; @Aspect @Component public class ServiceProxy { @Before(value="execution(* cn.mldn.service..*.*(..)) and args(id)",argNames="id") public void beforeMethod(Object obj) { System.out.println("###### [ServiceProxy] public void beforeMethod(){} ,参数内容:"+obj); } @After(value="execution(* cn.mldn.service..*.*(..))") public void afterMethod() { System.out.println("###### [ServiceProxy] public void afterMethod(){}"); } @AfterReturning(value="execution(* cn.mldn.service..*.*(..))",returning="v",argNames="v") public void returnMethod(Object val) { //处理返回值 System.out.println("###### [ServiceProxy] public void returnMethod(){} ,返回值:" + val); } @AfterThrowing(value="execution(* cn.mldn.service..*.*(..))",throwing="e",argNames="e") public void throwMethod(Exception e) { // 对异常进行处理 System.out.println("###### [ServiceProxy] public void throwMethod(){} 异常信息:" + e ); } @Around(value="execution(* cn.mldn.service..*.*(..))") public Object aroundMethod(ProceedingJoinPoint point) throws Throwable { //调用具体的执行方法 System.out.println("@@@@@@ aroundMethod() - before 参数:" + new Arrays().toString(point.getArgs())); //此时可以正对于参数接收后处理后再传递的操作 Object obj = point.proceed(new Object [] {"abc"}); System.out.println("@@@@@@ aroundMethod() - after 返回结果:" + obj); return true ; //还可以不按照结果返回数据 } }