SpringAOP的实现方式
1.使用原生SpringApi接口实现AOP:
-
首先我们写个UserService接口和它的实现类
public interface UserService { public void add(); } public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("add user"); } }
-
在applicationConte.xml导入命名空间。先搞切入点,再在切入点把Log.java切入进去。
<bean id="userService" class="com.zhou.service.UserServiceImpl"/>
<bean id="log" class="com.zhou.log.Log"/>
<bean id="afterLog" class="com.zhou.log.AfterLog"/>
<!-- 方式一:执行原生SpringApi接口-->
<aop:config>
<!-- 切入点 execution(第一个“*”表示返回值的类型任意 “com.zhou.service.UserServiceImpl”要执行的位置 “.*” 代表这个类下的所有方法 “..”代表可以有任意参数) -->
<aop:pointcut id="pointcut" expression="execution(* com.zhou.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕! 把log这个类切入到“* com.zhou.service.UserServiceImpl.*(..)”方法上面-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
- 前置和后置的Log
Log.java:
public class Log implements MethodBeforeAdvice {
// method:方法
//objects:参数
//o:对象
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");//某某对象的方法被执行了
}
}
AfterLog.java:
package com.zhou.log;
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] objects, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"返回的结果为"+returnValue);
}
}
- 测试代码如下
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//PS:动态代理的是接口
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
//报错了 因为没导入aspect依赖
}
- 输出结果
com.zhou.service.UserServiceImpl的add被执行了
add user
执行了add返回的结果为null
2.自定义类实现AOP
-
先写一个简单MyPointCut类
public class MyPointCut { public void before(){ System.out.println("我在方法执行前面"); } public void after(){ System.out.println("我在方法执行后面"); } }
-
另一种方式配置applicationConte.xml
<!--方式二:自定义类--> <bean id="diyPointCut" class="com.zhou.own.MyPointCut"/> <aop:config> <!--自定义切面 --> <aop:aspect ref="diyPointCut"> <!--切入点--> <aop:pointcut id="pointcut" expression="execution(* com.zhou.service.UserServiceImpl.*(..))"/> <!-- 通知--> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
-
测试一下
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); } }
输出结果:
我在方法执行前面
add user
我在方法执行后面 -
execution表达式:
<aop:pointcut id="pointcut" expression="execution(* com.zhou.service.UserServiceImpl.*(..))"/>
* 表示返回值的类型任意 com.zhou.service.UserServiceImpl 横切的业务类路径 .* 代表这个类下的所有方法 (..) ()代表参数,两个点代表可以有任意参数 3.使用注解实现AOP
-
MyPointCut.java
@Aspect public class AnnotationPointCut { @Before("execution(* com.zhou.service.UserServiceImpl.*(..))") public void before() { System.out.println("我在方法执行前面"); } @After("execution(* com.zhou.service.UserServiceImpl.*(..))") public void after() { System.out.println("我在方法执行后面"); }
-
关于环绕(@Around)
//在环绕增强中 我们可以给定一个参数 代表我们要处理切入的点 JointPoint:与切入点匹配的执行点 @Around("execution(* com.zhou.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("环绕前"); Object proceed = joinPoint.proceed();//执行方法 System.out.println("环绕后"); //Signature signature = joinPoint.getSignature(); //System.out.println("signature:" + signature.toString()); } }
-
配置文件
<!-- 方式三--> <bean id="annotationPointCut" class="com.zhou.own.AnnotationPointCut"/> <!-- 开启注解支持--> <aop:aspectj-autoproxy/>
-
输出结果:看看顺序= =
环绕前
我在方法执行前面
add user
我在方法执行后面
环绕后