zoukankan      html  css  js  c++  java
  • Spring AOP的用法

    AOP在事务处理、日志、安全等方面用的很多,在日常软件定制开发中,用好AOP可以进一步解耦,增强代码的可复用性。平时用的最多的还是Spring AOP动态代理,其用法如下:

    第一种实现的方式:通过Spring的API实现AOP。

    第一步:
    1. public interface UserService {
    2. public void add();
    3. public void update(int a);
    4. public void delete();
    5. public void search();
    6. }
    第二步:
    1. public class UserServiceImpl implements UserService {
    2. @Override
    3. public void add() {
    4. System.out.println("增加用户");
    5. }
    6. @Override
    7. public void update(int a) {
    8. System.out.println("修改用户");
    9. }
    10. @Override
    11. public void delete() {
    12. System.out.println("删除用户");
    13. }
    14. @Override
    15. public void search() {
    16. System.out.println("查询用户");
    17. }
    第三步:实现MethodBeforeAdvice的接口,Spring框架当中为我们提供了很多中通知。
    1. public class Log implements MethodBeforeAdvice{
    2. /**
    3. * @param method 被调用方法对象
    4. * @param args 被调用的方法的参数
    5. * @param target 被调用的方法的目标对象
    6. * */
    7. @Override
    8. public void before(Method method, Object[] args, Object target)
    9. throws Throwable {
    10. System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行");
    11. }
    12. }
    第四步:配置beans.xml文件
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean id="userService" class="com.spring.service.impl.UserServiceImpl"/>
    10. <!-- 这个切面也要配置成bean-->
    11. <bean id="log" class="com.spring.advice.Log"/>
    12. <aop:config>
    13. <!--切入点,需要告诉方法在什么去执行
    14. expression="execution(* com.spring.service.impl.*.*(..))"
    15. 第一个* 表示所有的返回值,然后就是包名
    16. 第二个*表示所有的类对象
    17. 第三个*表示类对象所有的方法
    18. 第四个*表示所有方法下面的带参数的方法或者是不带参数的方法
    19. -->
    20. <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/>
    21. <!-- 在所有的方法中都切入前置通知-->
    22. <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    23. </aop:config>
    24. </beans>
    第五步:测试:
    1. package com.spring.test;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. import com.spring.service.UserService;
    5. public class Test {
    6. public static void main(String[] args) {
    7. ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    8. UserService userService = (UserService)ac.getBean("userService");
    9. userService.update(2);
    10. userService.add();
    11. }
    12. }
    运行结果:
    1. 三月 12, 2017 2:22:44 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    2. 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 14:22:44 GMT+08:00 2017]; root of context hierarchy
    3. 三月 12, 2017 2:22:44 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    4. 信息: Loading XML bean definitions from class path resource [beans.xml]
    5. com.spring.service.impl.UserServiceImplupdate方法被执行
    6. 修改用户
    7. com.spring.service.impl.UserServiceImpladd方法被执行
    8. 增加用户
    故前置通知可以在spring当中被执行,接下可以完善通知;
    1. public class AfterLog implements AfterReturningAdvice{
    2. /**
    3. * 目标方法执行后执行的通知
    4. * returnValue--返回值
    5. * method 被调用的方法对象
    6. * args 被调用的方法对象的参数
    7. * target 被调用的方法对象的目标对象
    8. * */
    9. @Override
    10. public void afterReturning(Object returnValue, Method method,
    11. Object[] args, Object target) throws Throwable {
    12. System.out.println(target.getClass().getName()+"的"+method.getName()+"被成功执行,返回值是:"+returnValue);
    13. }
    14. }
     
    1. import java.lang.reflect.Method;
    2. import org.springframework.aop.ThrowsAdvice;
    3. public class ExceptionLog implements ThrowsAdvice {
    4. public void afterThrowing(Method method,Exception ex) throws Throwable {
    5. }
    6. }
    重新配置:
    1. <!-- 这个切面也要配置成bean-->
    2. <bean id="log" class="com.spring.advice.Log"/>
    3. <bean id="afterLog" class="com.spring.advice.AfterLog"></bean>
    4. <aop:config>
    5. <!--切入点,需要告诉方法在什么去执行
    6. expression="execution(* com.spring.service.impl.*.*(..))"
    7. 第一个* 表示所有的返回值,然后就是包名
    8. 第二个*表示所有的类对象
    9. 第三个*表示类对象所有的方法
    10. 第四个*表示所有方法下面的带参数的方法或者是不带参数的方法
    11. -->
    12. <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/>
    13. <!-- 在所有的方法中都切入前置通知-->
    14. <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    15. <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    16. </aop:config>
    测试运行结果:
    1. 三月 12, 2017 2:28:19 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    2. 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 14:28:19 GMT+08:00 2017]; root of context hierarchy
    3. 三月 12, 2017 2:28:19 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    4. 信息: Loading XML bean definitions from class path resource [beans.xml]
    5. com.spring.service.impl.UserServiceImpl的update方法被执行
    6. 修改用户
    7. com.spring.service.impl.UserServiceImpl的update被成功执行,返回值是:null
    8. com.spring.service.impl.UserServiceImpl的add方法被执行
    9. 增加用户
    10. com.spring.service.impl.UserServiceImpl的add被成功执行,返回值是:null
    总结:AOP的重要性,非常重要 
    Spring的AOP就是将公共的业务(如日志,安全等)和业务类结合。当执行业务的时候将会把公共业务加进来。实现公共业务的重复利用。我们自己的业务就会变得更加的纯粹,我们就可以关注我们的自己的业务,本质就是动态代理。
     
     
    第二种方式:自定义类来实现AOP,不实现spring的自带的通知
    第一步:重新通知:
    1. public class Log {
    2. public void before(){
    3. System.out.println("方法执行前");
    4. }
    5. public void after(){
    6. System.out.println("方法执行后");
    7. }
    8. }
    第二步:重新写配置文件
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean id="userService" class="com.spring.service.impl.UserServiceImpl"/>
    10. <!-- 这个切面也要配置成bean-->
    11. <bean id="log" class="com.spring.advice.Log"/>
    12. <aop:config>
    13. <!--切入点,需要告诉方法在什么去执行
    14. expression="execution(* com.spring.service.impl.*.*(..))"
    15. 第一个* 表示所有的返回值,然后就是包名
    16. 第二个*表示所有的类对象
    17. 第三个*表示类对象所有的方法
    18. 第四个*表示所有方法下面的带参数的方法或者是不带参数的方法
    19. -->
    20. <aop:aspect ref="log">
    21. <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/>
    22. <aop:before method="before" pointcut-ref="pointcut"/>
    23. <aop:after method="after" pointcut-ref="pointcut"/>
    24. </aop:aspect>
    25. </aop:config>
    26. </beans>
     
    第三种方式:通过注解实现AOP
    第一步:修改log
    1. package com.spring.advice;
    2. import java.lang.reflect.Method;
    3. import org.aspectj.lang.ProceedingJoinPoint;
    4. import org.aspectj.lang.annotation.After;
    5. import org.aspectj.lang.annotation.Around;
    6. import org.aspectj.lang.annotation.Aspect;
    7. import org.aspectj.lang.annotation.Before;
    8. import org.springframework.aop.MethodBeforeAdvice;
    9. @Aspect
    10. public class Log {
    11. @Before("execution(* com.spring.service.impl.*.*(..))")
    12. public void before(){
    13. System.out.println("方法执行前");
    14. }
    15. @After("execution(* com.spring.service.impl.*.*(..))")
    16. public void after(){
    17. System.out.println("方法执行后");
    18. }
    19. @Around("execution(* com.spring.service.impl.*.*(..))")
    20. public Object around(ProceedingJoinPoint jp) throws Throwable{
    21. System.out.println("环绕前");
    22. System.out.println("方法"+jp.getSignature());
    23. Object result=jp.proceed();
    24. System.out.println("环绕后");
    25. return result;
    26. }
    27. }
    第二步:修改beans.xml
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean id="userService" class="com.spring.service.impl.UserServiceImpl"/>
    10. <!-- 这个切面也要配置成bean-->
    11. <bean id="log" class="com.spring.advice.Log"/>
    12. <aop:aspectj-autoproxy/>
    13. </beans>
    第三步:运行:
    1. 三月 12, 2017 3:00:02 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    2. 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 15:00:02 GMT+08:00 2017]; root of context hierarchy
    3. 三月 12, 2017 3:00:02 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    4. 信息: Loading XML bean definitions from class path resource [beans.xml]
    5. 环绕前
    6. 方法void com.spring.service.UserService.update(int)
    7. 方法执行前
    8. 修改用户
    9. 环绕后
    10. 方法执行后

    Spring总结(五)--Spring中使用AOP三种方式

    里面最关键的切面配置如下:

  • 相关阅读:
    PHP 获取请求里的 header字段以及发送header
    宝塔链接数据库
    链表中头结点和头指针
    git How to resolve a Git “CONFLICT (modify/delete)”?
    yii 执行mysql:既要添加数据又要更新数据
    recv() failed (104: Connection reset by peer) while reading response header from upstream
    Linux磁盘空间满了,定位到mysql日志,删除
    mysql 字符乱码
    php message queue
    CGI 、fastcgi、php-cgi、php-fpm
  • 原文地址:https://www.cnblogs.com/doit8791/p/7697689.html
Copyright © 2011-2022 走看看