ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring学习--AOP的实现

2020-12-14 12:00:04  阅读:161  来源: 互联网

标签:userServiceImpl -- Spring void 接口 AOP UserService public


之前我谈到过动态代理:Spring学习-动态代理
动态代理里面很好地体现了AOP的思想,即面向切面编程:在不修改代码影响原有业务逻辑时,新增其他功能。
那么,在Spring中,如何实现AOP呢?

方法一:使用Spring的API接口

首先,需要新导入一个依赖:

<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.4</version>
</dependency>

接着,我们编写一个接口及其实现类:

package com.yyl.service;

/**
 * @Author: LongLongA
 * @Description:
 * @Date: Created in 9:51 2020/12/14
 */
public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}

package com.yyl.service;

/**
 * @Author: LongLongA
 * @Description:
 * @Date: Created in 9:51 2020/12/14
 */
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("add...");
    }

    @Override
    public void delete() {
        System.out.println("delete...");
    }

    @Override
    public void update() {
        System.out.println("update...");
    }

    @Override
    public void select() {
        System.out.println("select...");
    }
}

这时,我们设想一个应用场景:需要一个日志类,在每次接口方法被调用时,打印日志。
之前的时候,我们可以自己写一个关于接口的代理类来完成上述业务,与此同时,Spring框架也实现了相关接口:
首先,编写一个日志类,然后实现Spring中提供的接口:

package com.yyl.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * @Author: LongLongA
 * @Description:
 * @Date: Created in 10:08 2020/12/14
 */
public class MyLog implements MethodBeforeAdvice {
    @Override
    /*
    * method : 要执行的目标对象的方法
    * args : 方法所需参数
    * target: 被执行的目标(被切入的目标)
    *
    * */
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"被调用");
    }
}



这里,MethodBeforeAdvice接口表明该日志类需要执行的方法在指定业务之前。声明后,before里面的函数会在target对象中的method方法执行之前被调用。
之后我们再编写一个日志类:

package com.yyl.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/**
 * @Author: LongLongA
 * @Description:
 * @Date: Created in 10:18 2020/12/14
 */
public class MyLog2 implements AfterReturningAdvice {//该接口用于在target执行之后调用
    @Override
    // returnValue : 该参数用于接收返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
    }
}

以上事情做完后,我们需要在Spring容器中注册这些类,并且来配置AOP:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--注册Bean-->
    <bean id="userServiceImpl" class="com.yyl.service.UserServiceImpl"/>
    <bean id="myLog" class="com.yyl.log.MyLog"/>
    <bean id="myLog2" class="com.yyl.log.MyLog2"/>

    <!--配置AOP:需要导入aop的约束-->
    <aop:config>
        <!--
        定义切入点,即需要在哪个位置执行
        execution(要执行的类的位置)
        -->
        <aop:pointcut id="pointcut1" expression="execution(* com.yyl.service.UserServiceImpl.*(..))"/>

        <!--
            定义切入的方法,将其与切入点关联
            advice-ref属性值为切入方法的Id
            pointcut-ref属性值为切入点的id
        -->
        <aop:advisor advice-ref="myLog" pointcut-ref="pointcut1"/>
        <aop:advisor advice-ref="myLog2" pointcut-ref="pointcut1"/>
    </aop:config>

</beans>

下面是测试代码:

import com.yyl.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author: LongLongA
 * @Description:
 * @Date: Created in 11:35 2020/12/14
 */
public class MyTest {
    public static void main(String[] args) {
        //获取Spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
         //重点!!!:动态代理代理的是接口,所以返回值必须为接口,而不是它的实现类!!!
        UserService userServiceImpl = (UserService)context.getBean("userServiceImpl");
        userServiceImpl.add();
        userServiceImpl.delete();
        userServiceImpl.update();
        userServiceImpl.select();
    }
}

测试结果:
在这里插入图片描述
重点来了!!!!!
动态代理代理的是接口,所以返回值必须为接口,而不是它的实现类!!!
所以在此代码:
UserService userServiceImpl = (UserService)context.getBean("userServiceImpl");
返回值一定要是UserService接口,而不是它的实现类!!!
以后只要记住一点:“动态代理代理的是接口,而不是实现类”

方法二:未完待续。。。

标签:userServiceImpl,--,Spring,void,接口,AOP,UserService,public
来源: https://blog.csdn.net/theLuckyLong/article/details/111150616

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有