Spring API 接口和自定义类来实现AOP(Spring学习笔记十)

1、什么是AOP

全称是 Aspect Oriented Programming 即:面向切面编程。是OOP(面向对象编程)的延续,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。简单的说他就是把我们程序重复的代码抽取出来,在需要执行的时候使用动态代理技术在不修改源码的基础上,对我们的已有方法进行增强。

AOC在Spring中的作用

2、使用Spring实现AOP

方式一:使用Spring的API接口来做

1、导入AOP支持
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
    <scope>runtime</scope>
</dependency>
2、创建测试类

抽象类:

package com.li.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

抽象类实现:

package com.li.service;

public class UserServiceImp implements UserService{
    @Override
    public void add() {
        System.out.println("增加");
    }

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

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

    @Override
    public void select() {
        System.out.println("查询");
    }
}
 3、创建切面类,编写切面方法

方法一:实现MethodBeforeAdvice  在切入点之前切入方法

package com.li.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    //实现MethodBeforeAdvice会在方法执行前运行
    //method: 要执行的目标对象的方法
    //args:参数
    //target:目标对象
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了,"+"参数是:"+args.getClass().getName());
    }
}

方法二:实现 AfterReturningAdvice  在切入点后加入切面方法

package com.li.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    //实现AfterReturningAdvice会在方法执行后执行
    //method: 要执行的目标对象的方法
    //args:参数
    //target:目标对象
    //返回值:returnValue
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"执行了:"+method.getName()+"方法,方法参数是:"+args.getClass().toString()+"返回值是:"+returnValue);
    }
}
4、创建配置文件applicationContext.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
		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="UserService" class="com.li.service.UserServiceImp"/>
    <bean id="log" class="com.li.log.Log"/>
    <bean id="AfterLog" class="com.li.log.AfterLog"/>

    <!--使用原生Spring api接口-->
    <!--配置aop: 需要先导入aop的约束 xmlns:aop="http://www.springframework.org/schema/aop"    http://www.springframework.org/schema/aop
		https://www.springframework.org/schema/aop/spring-aop.xsd"-->
    <aop:config>
    <!--需要一个切入点就是我们需要在什么地方去执行我们的Spring的方法-->
    <!--id后面接你想给切入点取的名字 expression需要接表达式,表达式是死的:execution(* 要执行的位置.*(..))    这里的.*表示位置下的所有方法 (..)表示可以有任意的参数-->
        <aop:pointcut id="poi" expression="execution(* com.li.service.UserServiceImp.*(..))"/>

    <!--执行环绕增强-->
        <aop:advisor advice-ref="log" pointcut-ref="poi"/>
        <aop:advisor advice-ref="AfterLog" pointcut-ref="poi"/>
    </aop:config>
</beans>
5、测试类测试
package com.li.log;

import com.li.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestGo {
    @Test
    public void test1(){
        //通过配置文件获取ClassPath
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //根据抽象类获取Bean
        UserService user = context.getBean("UserService", UserService.class);
        //调用方法测试
        user.add();

    }
}

 测试结果

方式二:使用自定义类来实现Aop

创建自定义类和方法

package com.li.diy;

public class Diy {
    public void before(){
        System.out.println("====切面之前执行====");
    }

    public void after(){
        System.out.println("====切面之后执行====");
    }
}

配置applicationContext.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
		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="UserService" class="com.li.service.UserServiceImp"/>

    <!--方式二: 通过自定义方法来Aop-->
    <!--注册Bean-->
    <bean id="diy" class="com.li.diy.Diy"/>

    <!--配置aop: 需要先导入aop的约束 xmlns:aop="http://www.springframework.org/schema/aop"    http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd"-->
    <aop:config>

    <!--自定义切面,ref:接需要引用类的bean id-->
        <aop:aspect ref="diy">

            <!--id后面接你想给切入点取的名字 expression需要接表达式,表达式是死的:execution(* 要执行的位置.*(..))    这里的.*表示位置下的所有方法 (..)表示可以有任意的参数-->
            <aop:pointcut id="point" expression="execution(* com.li.service.UserServiceImp.*(..))"/>

            <!--通知 method后接前面类中自定义的方法名 pointcut-ref后接切入点的id -->
            <aop:before method="before" pointcut-ref="point"/>

            <aop:after method="after" pointcut-ref="point"/>


        </aop:aspect>

    </aop:config>
</beans>

创建测试类

package com.li.log;

import com.li.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestGo {
    @Test
    public void test1(){
        //通过配置文件获取ClassPath
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //根据抽象类获取Bean
        UserService user = context.getBean("UserService", UserService.class);
        //调用方法测试
        user.add();

    }
}

 测试结果

  • 12
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一年找不到工作就去厂里大螺丝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值