Spring学习:通过环绕增强类缓存目标对象执行结果

简介:通过环绕增强类缓存目标对象执行结果,所表达的意思是:通过代理类代理执行目标对象的方法时,将执行结果存储到定义的缓存中(这里用HashMap来定义缓存对象),当再次执行相同的方法时(即方法名、方法参数、和目标对象都相同),不会再从目标对象(被代理对象)中过行代码,而是直接从缓存中(HashMap)取出,这样,加快了代码整体的运行速度。以缓存计算结果为例,具体实现代码示例如下:

一、定义接口及实现接口

(一) 定义接口,这里定义的接口用于最基本的计算
public interface CalcService {
    int addNumber(int a,int b);

    int minNumber(int a,int b);
}
(二) 实现接口
public class CalcServiceImpl implements CalcService {

    @Override
    public int addNumber(int a, int b) {
        System.out.println("开始执行加法计算:");
        return a + b;
    }

    @Override
    public int minNumber(int a, int b) {
        System.out.println("开始执行减法计算:");
        return a-b;
    }
}

二、定义用于缓存的环绕增强类(重点)


public class BeforeAndAfterAdvice implements MethodInterceptor {

    // TODO: 2021/6/28 这个地方定义了一个缓存
    Map<CalcServiceKey, Object> map = new HashMap<>();

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {

        Method method = methodInvocation.getMethod();
        Object[] arguments = methodInvocation.getArguments();
        Object aThis = methodInvocation.getThis();

        CalcServiceKey calcServiceKey = new CalcServiceKey();
        calcServiceKey.setMethod(method);
        calcServiceKey.setTarget(aThis);
        calcServiceKey.setArgs(arguments);

        // TODO: 2021/6/28 如果存在全部一样的Key,则直接返回对象,从而跳远了目标对象方法的很执行!
        if (map.containsKey(calcServiceKey)) {
            System.out.println("直接从Map集合中读取!!");
            return map.get(calcServiceKey);
        }

        System.out.println("将继续执行目标对象中的方法!");

        // TODO: 2021/6/28 执行目标对象代码
        Object proceed = methodInvocation.proceed();

        // TODO: 2021/6/28 如果在Map集合中没有存在的key,则将key和值都放进去
        map.put(calcServiceKey, proceed);
        return proceed;
    }
}

三、定义用于存放方法结构信息、参数信息和目标对象信息的对象(重点)

HashMap可以自动判断存放到HashMap集合的数据键值(Key)是否相同,而做为通过字节码操作工作类生成的代理类字节码,要判断调用的方法、参数和目标对象是否相同,就必须 自定义一个类,用于存放这三者的信息。同时必须重写hashcode()和euqeals()方法,当存放到HashMap集合中时,用于比较是否存在相同的键值。这个用于存放方法结构信息,参数信息和目标对象的自定义类示例代码如下:


public class CalcServiceKey {

    private Method method;
    private Object[] args;
    private Object target;

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Object[] getArgs() {
        return args;
    }

    public void setArgs(Object[] args) {
        this.args = args;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CalcServiceKey that = (CalcServiceKey) o;
        return Objects.equals(method, that.method) &&
                Arrays.equals(args, that.args) &&
                Objects.equals(target, that.target);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(method, target);
        result = 31 * result + Arrays.hashCode(args);
        return result;
    }
}

四、配置xml核心配置文件,在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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- TODO:1.生成目标对象实例 -->
    <bean id="calcserviceimpl" class="aop1.impl.CalcServiceImpl"/>
    <!-- TODO:2.生成环绕增强类实例 -->
    <bean id="calcserviceadvice" class="aop1.advice.BeforeAndAfterAdvice"/>
    <!-- TODO:明定增强类实例映射到的切入点 -->
    <bean id="calcserviceadvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="calcserviceadvice"/>
        <property name="mappedNames">
            <list>
                <value>*</value>
            </list>
        </property>
    </bean>
    <!-- TODO:生成代理对象实例 -->
    <bean id="calcserviceproxybean" class="org.springframework.aop.framework.ProxyFactoryBean" lazy-init="false">
        <property name="target" ref="calcserviceimpl"/>
        <property name="interfaces">
            <list>
                <value>aop1.CalcService</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>calcserviceadvisor</value>
            </list>
        </property>
    </bean>

</beans>

五、测试运行

    @Test
    public void test25() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop1/aop1.xml");
        CalcService calcserviceproxybean = (CalcService) ac.getBean("calcserviceproxybean");
        System.out.println(calcserviceproxybean.addNumber(20, 30));
        System.out.println(calcserviceproxybean.addNumber(20, 30));
    }

五、最终运行结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值