欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring中AOP实现

程序员文章站 2024-02-29 11:52:28
...

AOP是面向切面编程,这种方式底层是代理模式,在Spring中提供声明式事务,允许用户自定义切面,这里以添加日志来进行讲解,在我们写好的CRUD中横切式的加入日志。

方式一:使用Spring中原生的API实现,它通过Advice定义横切逻辑,提供了5种类型的Advice

Spring中AOP实现

 在导入了Spring的依赖之后还需导入AOP的依赖包

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

然后写我们的业务接口

package com.zhiying.service;

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

业务实现类

package com.zhiying.service;

public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("add");
    }

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

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

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

然后是我们新增的日志功能,包括前置日志和后置日志

package com.zhiying.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class BeforeLog implements MethodBeforeAdvice {

    //method要执行的目标对象的方法
    //ags参数
    //target目标对象
    public void before(Method method, Object[] ags, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+ "的" + method.getName() + "被执行了");
    }
}
package com.zhiying.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    //returnValue返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了" + method.getName() + "返回结果为" + returnValue);
    }
}

然后是配置文件

<?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 id="userService" class="com.zhiying.service.UserServiceImpl"/>
    <bean id="afterLog" class="com.zhiying.log.AfterLog"/>
    <bean id="beforeLog" class="com.zhiying.log.BeforeLog"/>
<!--配置aop需要导入aop的约束-->
    <aop:config>
<!--        切入点 execution(要执行的位置:修饰词,返回值,类名,方法名,参数)可用* -->
        <aop:pointcut id="pointcut" expression="execution(* com.zhiying.service.UserServiceImpl.*(..))"/>
<!--        执行环绕增加-->
        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>

    </aop:config>

</beans>

测试

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

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService service = (UserService) context.getBean("userService");
        service.add();
        service.delete();
    }
}

Spring中AOP实现

用Spring实现了,业务和日志的分离,Service和Log的任务都很纯粹,只需用Spring这个中间代理进行切入即可

方式二:自定义类来实现

在方法一的基础上新建一个diy类

package com.zhiying.diy;

public class Diy {
    public void beforeLog() {
        System.out.println("执行之前");
    }
    public void afterLog() {
        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
        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 id="userService" class="com.zhiying.service.UserServiceImpl"/>
<!--    <bean id="afterLog" class="com.zhiying.log.AfterLog"/>-->
<!--    <bean id="beforeLog" class="com.zhiying.log.BeforeLog"/>-->

<!--    方式一-->
<!--&lt;!&ndash;配置aop需要导入aop的约束&ndash;&gt;-->
<!--    <aop:config>-->
<!--&lt;!&ndash;        切入点 execution(要执行的位置:修饰词,返回值,类名,方法名,参数)可用* &ndash;&gt;-->
<!--        <aop:pointcut id="pointcut" expression="execution(* com.zhiying.service.UserServiceImpl.*(..))"/>-->
<!--&lt;!&ndash;        执行环绕增加&ndash;&gt;-->
<!--        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>-->
<!--        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
<!--    </aop:config>-->

<!--    方式二 自定义类-->
    <bean id="diy" class="com.zhiying.diy.Diy"/>
    <aop:config>
        <!--自定义切面 ref是要引用的类-->
        <aop:aspect ref="diy">
<!--            切入点-->
            <aop:pointcut id="point" expression="execution(* com.zhiying.service.UserServiceImpl.*(..))"/>
<!--            通知-->
            <aop:before method="beforeLog" pointcut-ref="point"/>
            <aop:after method="afterLog" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>

其他的不变,直接运行即可

Spring中AOP实现

方式三:注解实现,这里我们再写一个类,该类也是实现日志的功能,并且使用了注解

package com.zhiying.diy;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect //标注这是一个切面
public class AnnotationPointCut {

    @Before("execution(* com.zhiying.service.UserServiceImpl.*(..))")
    public void beforeLog() {
        System.out.println("---方法执行前---");
    }

    @After("execution(* com.zhiying.service.UserServiceImpl.*(..))")
    public void afterLob() {
        System.out.println("---方法执行后---");
    }
}

下面是配置文件,主要用来对业务bean的注入,以及对注解的支持

<?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 id="userService" class="com.zhiying.service.UserServiceImpl"/>
<!--    <bean id="afterLog" class="com.zhiying.log.AfterLog"/>-->
<!--    <bean id="beforeLog" class="com.zhiying.log.BeforeLog"/>-->

<!--    方式一-->
<!--&lt;!&ndash;配置aop需要导入aop的约束&ndash;&gt;-->
<!--    <aop:config>-->
<!--&lt;!&ndash;        切入点 execution(要执行的位置:修饰词,返回值,类名,方法名,参数)可用* &ndash;&gt;-->
<!--        <aop:pointcut id="pointcut" expression="execution(* com.zhiying.service.UserServiceImpl.*(..))"/>-->
<!--&lt;!&ndash;        执行环绕增加&ndash;&gt;-->
<!--        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>-->
<!--        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
<!--    </aop:config>-->

<!--    方式二 自定义类-->
<!--    <bean id="diy" class="com.zhiying.diy.Diy"/>-->
<!--    <aop:config>-->
<!--        &lt;!&ndash;自定义切面 ref是要引用的类&ndash;&gt;-->
<!--        <aop:aspect ref="diy">-->
<!--&lt;!&ndash;            切入点&ndash;&gt;-->
<!--            <aop:pointcut id="point" expression="execution(* com.zhiying.service.UserServiceImpl.*(..))"/>-->
<!--&lt;!&ndash;            通知&ndash;&gt;-->
<!--            <aop:before method="beforeLog" pointcut-ref="point"/>-->
<!--            <aop:after method="afterLog" pointcut-ref="point"/>-->
<!--        </aop:aspect>-->
<!--    </aop:config>-->
    <!--    方式三注解-->
    <bean id="annotationPointCut" class="com.zhiying.diy.AnnotationPointCut"/>
<!--    注解驱动支持-->
    <aop:aspectj-autoproxy/>
</beans>

其他不变,运行即可

Spring中AOP实现

相关标签: Java框架