当前位置:   article > 正文

spring——AOP的前置通知、后置通知、环绕通知、异常通知_环绕通知和前置通知的区别

环绕通知和前置通知的区别

准备:aopliance.jar、aspect jweaver.jar

方法:确定一个切入点方法

配置:将通知文件和方法关联起来

举例方法:addStudent

StudentServiceImpl.java

  1. package com.dt.service.impl;
  2. import org.springframework.transaction.annotation.Propagation;
  3. import org.springframework.transaction.annotation.Transactional;
  4. import com.dt.dao.IStudentDao;
  5. import com.dt.dao.impl.StudentDaoImpl;
  6. import com.dt.entity.Student;
  7. import com.dt.service.IStudentService;
  8. public class StudentServiceImpl implements IStudentService{
  9. IStudentDao studentDao;
  10. public void setStudentDao(IStudentDao studentDao) {
  11. this.studentDao = studentDao;
  12. }
  13. @Override
  14. public void addStudnet(Student student) {
  15. studentDao.addStudent(student);
  16. }
  17. }

test.java

  1. package com.dt.test;
  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. import com.dt.entity.AllCollectionType;
  5. import com.dt.entity.Course;
  6. import com.dt.entity.Student;
  7. import com.dt.service.IStudentService;
  8. public class test {
  9. public static void main(String[] args) {
  10. testAOP();
  11. }
  12. public static void testAOP(){
  13. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  14. //需要获取的bean的id值,可进行强制类型转换成类的类型
  15. IStudentService studentService= (IStudentService)context.getBean("studentService");
  16. Student student=new Student();
  17. student.setAge(24);
  18. student.setName("刘昊然");
  19. student.setId(2);
  20. studentService.addStudnet(student);
  21. }
  22. }

1、前置通知:每当执行一个切入点方法之前,自动执行的一个方法

将自动执行得方法实现MethodBeforeAdvice接口,并实现里面的方法

LogBefore.java

  1. package com.dt.aop;
  2. import java.lang.reflect.Method;
  3. import org.springframework.aop.MethodBeforeAdvice;
  4. //前置通知
  5. public class LogBefore implements MethodBeforeAdvice{
  6. @Override
  7. public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
  8. System.out.println("前置通知");
  9. }
  10. }

applicationContext.xml

aop:config将切入方法和通知进行关联的配置:

aop:pointcut标签配置切入点:expression指定切入方法,在方法名前要加上包名.类名两个execution之间可以用or连接

aop:advisor标签将切入点和切面联系起来:属性advice-ref:指向通知的bean的id;属性pointcut-ref指向配置切入点的id

  1. <bean id="studentDao" class="com.dt.dao.impl.StudentDaoImpl"></bean>
  2. <!-- 配置实现类addStudent()所在的方法 -->
  3. <bean id="studentService" class="com.dt.service.impl.StudentServiceImpl">
  4. <property name="studentDao" ref="studentDao"></property>
  5. </bean>
  6. <!-- 配置前置通知所在类 -->
  7. <bean id="logBefore" class="com.dt.aop.LogBefore"></bean>
  8. <!-- 将方法所在类和通知进行关联 -->
  9. <aop:config>
  10. <!-- 配置切入点 (在哪里执行通知 expression)-->
  11. <aop:pointcut expression="execution(public void com.dt.service.impl.StudentServiceImpl.addStudnet(com.dt.entity.Student))" id="pointcut"/>
  12. <!-- 关联:连接切入点和切面的线 -->
  13. <aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
  14. </aop:config>

2、后置通知:在一个指定的方法执行后,自动执行

需要实现AfterReturningAdvice的接口和接口里的方法

  1. /**
  2. *
  3. */
  4. package com.dt.aop;
  5. import java.lang.reflect.Method;
  6. import org.springframework.aop.AfterReturningAdvice;
  7. /**
  8. * @author DT
  9. *后置通知
  10. */
  11. public class LogAfter implements AfterReturningAdvice{
  12. @Override
  13. public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
  14. System.out.println("后置通知:目标对象:"+target+",调用的方法名"+method.getName()+",方法的参数个数:"+args.length+",方法的返回值:"+returnValue);
  15. }
  16. }

applicationContext.xml

  1. <aop:config>
  2. <!-- 配置切入点 (在哪里执行通知 expression)-->
  3. <aop:pointcut expression="execution(public void com.dt.service.impl.StudentServiceImpl.addStudnet(com.dt.entity.Student))" id="pointcut2"/>
  4. <!-- 关联:连接切入点和切面的线 -->
  5. <aop:advisor advice-ref="logAfter" pointcut-ref="pointcut2"/>
  6. </aop:config>
  7. <bean id="logAfter" class="com.dt.aop.LogAfter"></bean>

3、异常通知:实现ThrowsAdvice接口,实现接口里的方法

public void afterThrowing([Method, args, target], ThrowableSubclass);//[]三个参数全写,或者不写

LogException.java

  1. package com.dt.aop;
  2. import java.lang.reflect.Method;
  3. import org.springframework.aop.ThrowsAdvice;
  4. /**
  5. * @author DT
  6. *异常通知
  7. */
  8. public class LogException implements ThrowsAdvice{
  9. //异常通知
  10. public void afterThrowing(Method method, Object[] args, Object target, Throwable ex){
  11. System.out.println("异常通知:目标对象:"+target+",方法名"+method.getName()+",方法得参数个数:"+args.length+",异常类型:"+ex.getMessage());
  12. }
  13. }

applicationContext.xml

  1. <!-- 异常通知 -->
  2. <bean id="logAround" class="com.dt.aop.LogAround"></bean>
  3. <aop:config>
  4. <!-- 配置切入点 (在哪里执行通知 expression)-->
  5. <aop:pointcut expression="execution(public void com.dt.service.impl.StudentServiceImpl.addStudnet(com.dt.entity.Student))" id="pointcut4"/>
  6. <!-- 关联:连接切入点和切面的线 -->
  7. <aop:advisor advice-ref="logAround" pointcut-ref="pointcut4"/>
  8. </aop:config>

4、环绕通知:在目标方法得前后、异常发生时、最终等各个地方都可以进行的通知。可以获取目标方法的全部控制权(目标方法是否执行、执行之前、执行之后、参数、返回值等)

环绕通知一个可以替代其余的三个;

在使用环绕通知时,目标方法得一切信息  都可以通过invocation参数获取到

LogAround.java

  1. /**
  2. *
  3. */
  4. package com.dt.aop;
  5. import org.aopalliance.intercept.MethodInterceptor;
  6. import org.aopalliance.intercept.MethodInvocation;
  7. /**
  8. * @author DT
  9. *环绕通知
  10. */
  11. public class LogAround implements MethodInterceptor{
  12. @Override
  13. public Object invoke(MethodInvocation invocation) throws Throwable {
  14. Object result=null;
  15. //方法体
  16. try{
  17. //invocation.proceed()在此方法前得称为前置通知
  18. System.out.println("用环绕通知实行的前置通知");
  19. //控制目标方法的执行:即写了执行addStudent(),
  20. //result就是目标方法的返回值
  21. result=invocation.proceed();
  22. //invocation.proceed()在此方法后得称为后置通知
  23. System.out.println("用环绕通知实行的后置通知");
  24. }catch(Exception e){
  25. //invocation.proceed()在catch里面就是异常通知
  26. System.out.println("用环绕通知实行的异常通知");
  27. }
  28. //result:目标方法的返回值
  29. return result;
  30. }
  31. }

通过invocation可得到前置、后置、异常的值

  1. /**
  2. *
  3. */
  4. package com.dt.aop;
  5. import org.aopalliance.intercept.MethodInterceptor;
  6. import org.aopalliance.intercept.MethodInvocation;
  7. /**
  8. * @author DT
  9. *环绕通知
  10. */
  11. public class LogAround implements MethodInterceptor{
  12. @Override
  13. public Object invoke(MethodInvocation invocation) throws Throwable {
  14. Object result=null;
  15. //方法体
  16. try{
  17. //invocation.proceed()在此方法前得称为前置通知
  18. System.out.println("用环绕通知实行的前置通知:目标对象:"+invocation.getThis()+",调用的方法名"+invocation.getMethod().getName()+",方法的参数个数:"+invocation.getArguments().length+",方法的返回值:"+result);
  19. //控制目标方法的执行:即写了执行addStudent(),
  20. //result就是目标方法的返回值
  21. result=invocation.proceed();
  22. //invocation.proceed()在此方法后得称为后置通知
  23. System.out.println("用环绕通知实行的后置通知:目标对象:"+invocation.getThis()+",调用的方法名"+invocation.getMethod().getName()+",方法的参数个数:"+invocation.getArguments().length+",方法的返回值:"+result);
  24. }catch(Exception e){
  25. //invocation.proceed()在catch里面就是异常通知
  26. System.out.println("用环绕通知实行的异常通知");
  27. }
  28. //result:目标方法的返回值
  29. return result;
  30. }
  31. }

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/675009
推荐阅读
相关标签
  

闽ICP备14008679号