实现AOP

AOP(例:spring-09-aop,相关文件在最下方,不一定还可以运行,但功能用法都相同,可以参考重写)


方法一:使用Spring实现AOP


步骤一:使用AOP前需要导入依赖包

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

步骤二:在resources文件夹下创建 ‘.xml’ 文件,配置如下:

<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"></beans>

步骤三:编写基本功能的接口和实现类,例如spring-09-aop的UserService和UserServiceImpl
UserService类:

package com.guan.service;

/**
 * @author gys
 * @since 2021-12-13
 */
public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

UserServiceImpl类:

package com.guan.service;

/**
 * @author gys
 * @since 2021-12-13
 */
public class UserServiceImpl 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("查询了一个用户");
    }
}


步骤四:编写 接口 AfterReturningAdvice 和 接口 MethodBeforeAdvice的实现类,例如 spring-09-aop 的 AfterLog 和 BeforeLog

AfterReturningAdvice 作用为:在方法被调用后自动执行并返回一个值
MethodBeforeAdvice 作用为:在方法被调用前自动执行

AfterLog类 :

package com.guan.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/**
 * @author gys
 * @since 2021-12-13
 */
public class AfterLog02 implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("【方法一】后置日志(After):"+target.getClass().getName()+"类的"+method.getName()+"方法被执行了【方法一】");
    }
}

BeforeLog类:

package com.guan.log;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
 * @author gys
 * @since 2021-12-13
 */
public class BeforeLog02 implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("【方法一】前置日志(Before):"+target.getClass().getName()+"类的"+method.getName()+"方法被执行了【方法一】");
    }
}


步骤五:在步骤二创建的 。xml 文件里装配对象,把所有定义的类都装配完成

可以采用自动装配,也可以采用bean进行手动装配

手动装配

	<bean id="userService" class="com.guan.service.UserServiceImpl"/>
    <bean id="beforeLog" class="com.guan.log.BeforeLog"/>
    <bean id="afterLog" class="com.guan.log.AfterLog"/>
    <bean id="beforeLog02" class="com.guan.log.BeforeLog02"/>
    <bean id="afterLog02" class="com.guan.log.AfterLog02"/>
    <bean id="diyPointCut" class="com.guan.diy.DiyPointCut"/>

步骤六:定义切入点pointcut,切入点用来指向被代理对象

<aop:pointcut id="pointcut" expression="execution(* com.guan.service.UserServiceImpl.*(..))"/>  

作用:id为 pointcut的 切入点,定位了 com.guan.service.UserServiceImpl类 中的所有方法
第一个代表是任意的返回类型, .(…)代表了 类中的所有方法,且 括号里的 … 代表了任意的参数


步骤七:通过切入点把步骤五装配的其中用来实现AfterReturningAdvice和MethodBeforeAdvice接口的实现类 切入进 切入点指向的被代理对象

 <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut" />
  • 结果为:
    被装配对象beforeLog 指向 pointcut 定位的 UserServiceImpl类中的所有方法,且因为beforeLog是实现了接口MethodBeforeAdvice
    所以会在调用UserServiceImpl类中的任意方法时,在这之前自动调用beforeLog的实现接口的方法

步骤八:在main函数里通过获取 context 和 使用 context。getBean(“装配对象”,接口名.class)来生成动态代理对象
ApplicationContext context = new ClassPathXmlApplicationContext(“xml的文件名”);
接口名 自定义的代理对象名 = context.getBean(“xml文件中已经装配的对象名”,接口名.class);


步骤九:当通过动态代理对象调用被代理对象被execution函数指定的方法时,会自动调用步骤五切入进 切入点的两种实现类


方法二:自定义类(在spring-09-aop的applicationContext.xml文件)

  • 主要是采用切面定义
  <aop:aspect ref="diyPointCut">
  <!--切入点-->
  <aop:pointcut id="pointcut02" expression="execution(* com.guan.service.UserServiceImpl.*(..))"/>  
  <!--通知-->  
  <aop:before method="before" pointcut-ref="pointcut02" />  
  <aop:after method="after" pointcut-ref="pointcut02" />  
  </aop:aspect>

方法三:采用注解实现AOP

这一部分 在spring-09-aop文件夹下的
anno文件下的AnnotationPointCut类 和
resources 文件夹下的 applicationContext 文件 内注释的方法三一起看
####第一步:在xml文件里配置注解所必须的文件并在pom里导入需要的两个包:spring-webmvc,aspectjweaver
1.首先在xml的头里添加这些进去
xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd

2.在在beans内写入一下两条代码:实现自动装配对象
a) 开启注解支持:<context:annotation-config/> 为了能在类上一行使用@Component自动装配对象
b) 指定要扫描的包:<context:component-scan base-package=“com.guan”/> 设置注解支持的范围,配合@Component使用

3.继续写入,开启切入面的注解支持:aop:aspectj-autoproxy/
a) 开启后有四个内容,@Aspect,@Before,@After,@Around
b) 查看spring-09-aop 的anno文件下的AnnotationPointCut类可了解具体用途

相关文件:
spring-study
链接:https://pan.baidu.com/s/1YWbZJ_EGWyJInxBtR9c1UQ
提取码:bjfu

上一篇:AOP 概念篇


下一篇:设计模式-Decorator装饰器