• Spring中使用AOP三种方式



    title:Spring中使用AOP三种方式
    date: 2018-10-29 22:32:01
    tags: spring
    author :辰砂tj


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

    第一步:

    public interface UserService {
    public void add();
    public void update(int a);
    public void delete();
    public void search();
    }
    

    第二步:

    public class UserServiceImpl implements UserService {
    @Override
    public void add() {
    System.out.println("增加用户");
    }
    @Override
    public void update(int a) {
    System.out.println("修改用户");
    }
    @Override
    public void delete() {
    System.out.println("删除用户");
    }
    @Override
    public void search() {
    System.out.println("查询用户");
    }
    

    第三步:实现MethodBeforeAdvice的接口,Spring框架当中为我们提供了很多中通知。

    public class Log implements MethodBeforeAdvice{
    /**
    * @param method 被调用方法对象
    * @param args 被调用的方法的参数
    * @param target 被调用的方法的目标对象
    * */
    @Override
    public void before(Method method, Object[] args, Object target)
    throws Throwable {
    System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行");
    }
    }
    

    第四步:配置beans.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.spring.service.impl.UserServiceImpl"/>
    <!-- 这个切面也要配置成bean-->
    <bean id="log" class="com.spring.advice.Log"/>
    <aop:config>
    <!--切入点,需要告诉方法在什么去执行
    expression="execution(* com.spring.service.impl.*.*(..))"
    第一个* 表示所有的返回值,然后就是包名
    第二个*表示所有的类对象
    第三个*表示类对象所有的方法
    第四个*表示所有方法下面的带参数的方法或者是不带参数的方法
    -->
    <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/>
    <!-- 在所有的方法中都切入前置通知-->
    <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    </aop:config>
    </beans>
    

    第五步:测试:

    package com.spring.test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import com.spring.service.UserService;
    public class Test {
    public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    UserService userService = (UserService)ac.getBean("userService");
    userService.update(2);
    userService.add();
    }
    }
    

    运行结果:

    三月 12, 2017 2:22:44 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 14:22:44 GMT+08:00 2017]; root of context hierarchy
    三月 12, 2017 2:22:44 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [beans.xml]
    com.spring.service.impl.UserServiceImpl的update方法被执行
    修改用户
    com.spring.service.impl.UserServiceImpl的add方法被执行
    增加用户
    故前置通知可以在spring当中被执行,接下可以完善通知;
    
    
    public class AfterLog implements AfterReturningAdvice{
    /**
    * 目标方法执行后执行的通知
    * returnValue--返回值
    * method 被调用的方法对象
    * args 被调用的方法对象的参数
    * target 被调用的方法对象的目标对象
    * */
    @Override
    public void afterReturning(Object returnValue, Method method,
    Object[] args, Object target) throws Throwable {
    System.out.println(target.getClass().getName()+"的"+method.getName()+"被成功执行,返回值是:"+returnValue);
    }
    }
    
    import java.lang.reflect.Method;
    import org.springframework.aop.ThrowsAdvice;
    public class ExceptionLog implements ThrowsAdvice {
    public void afterThrowing(Method method,Exception ex) throws Throwable {
    }
    }
    

    重新配置:

    <!-- 这个切面也要配置成bean-->
    <bean id="log" class="com.spring.advice.Log"/>
    <bean id="afterLog" class="com.spring.advice.AfterLog"></bean>
    <aop:config>
    <!--切入点,需要告诉方法在什么去执行
    expression="execution(* com.spring.service.impl.*.*(..))"
    第一个* 表示所有的返回值,然后就是包名
    第二个*表示所有的类对象
    第三个*表示类对象所有的方法
    第四个*表示所有方法下面的带参数的方法或者是不带参数的方法
    -->
    <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/>
    <!-- 在所有的方法中都切入前置通知-->
    <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
    

    测试运行结果:

    三月 12, 2017 2:28:19 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 14:28:19 GMT+08:00 2017]; root of context hierarchy
    三月 12, 2017 2:28:19 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [beans.xml]
    com.spring.service.impl.UserServiceImpl的update方法被执行
    修改用户
    com.spring.service.impl.UserServiceImpl的update被成功执行,返回值是:null
    com.spring.service.impl.UserServiceImpl的add方法被执行
    增加用户
    com.spring.service.impl.UserServiceImpl的add被成功执行,返回值是:null
    

    总结:AOP的重要性,非常重要

    Spring的AOP就是将公共的业务(如日志,安全等)和业务类结合。当执行业务的时候将会把公共业务加进来。实现公共业务的重复利用。我们自己的业务就会变得更加的纯粹,我们就可以关注我们的自己的业务,本质就是动态代理。

    第二种方式:自定义类来实现AOP,不实现spring的自带的通知

    第一步:重新通知:

    public class Log {
    public void before(){
    System.out.println("方法执行前");
    }
    public void after(){
    System.out.println("方法执行后");
    }
    }
    

    第二步:重新写配置文件

    <?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.spring.service.impl.UserServiceImpl"/>
    <!-- 这个切面也要配置成bean-->
    <bean id="log" class="com.spring.advice.Log"/>
    <aop:config>
    <!--切入点,需要告诉方法在什么去执行
    expression="execution(* com.spring.service.impl.*.*(..))"
    第一个* 表示所有的返回值,然后就是包名
    第二个*表示所有的类对象
    第三个*表示类对象所有的方法
    第四个*表示所有方法下面的带参数的方法或者是不带参数的方法
    -->
    <aop:aspect ref="log">
    <aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))" id="pointcut"/>
    <aop:before method="before" pointcut-ref="pointcut"/>
    <aop:after method="after" pointcut-ref="pointcut"/>
    </aop:aspect>
    </aop:config>
    </beans>
    

    第三种方式:通过注解实现AOP

    第一步:修改log

    package com.spring.advice;
    import java.lang.reflect.Method;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.aop.MethodBeforeAdvice;
    @Aspect
    public class Log {
    @Before("execution(* com.spring.service.impl.*.*(..))")
    public void before(){
    System.out.println("方法执行前");
    }
    @After("execution(* com.spring.service.impl.*.*(..))")
    public void after(){
    System.out.println("方法执行后");
    }
    @Around("execution(* com.spring.service.impl.*.*(..))")
    public Object around(ProceedingJoinPoint jp) throws Throwable{
    System.out.println("环绕前");
    System.out.println("方法"+jp.getSignature());
    Object result=jp.proceed();
    System.out.println("环绕后");
    return result;
    }
    }
    

    第二步:修改beans.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.spring.service.impl.UserServiceImpl"/>
    <!-- 这个切面也要配置成bean-->
    <bean id="log" class="com.spring.advice.Log"/>
    <aop:aspectj-autoproxy/>
    </beans>
    

    第三步:运行:

    三月 12, 2017 3:00:02 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@439f5b3d: startup date [Sun Mar 12 15:00:02 GMT+08:00 2017]; root of context hierarchy
    三月 12, 2017 3:00:02 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [beans.xml]
    环绕前
    方法void com.spring.service.UserService.update(int)
    方法执行前
    修改用户
    环绕后
    方法执行后
    
  • 相关阅读:
    MYSQL数据类型——字符串类型
    MYSQL——记录长度
    MYSQL数据类型——时间日期类型
    MYSQL数据类型——数值类型
    为什么在 IDEA jsp 中直接使用 out.println 会出错
    花指令行为大赏
    EasyCpp 题解
    [SUCTF2019] hardcpp 题解
    洛谷 P1650 田忌赛马题解
    Dict 协议是什么
  • 原文地址:https://www.cnblogs.com/tojian/p/9867886.html
Copyright © 2020-2023  润新知