静态代理模拟spring中AOP

1.1 目的

通过静态代理模拟spring中aop,使用静态代理拆分业务和业务接口,切面和切面接口,降低耦合,从而达到灵活拓展业务,为理解动态代理aop做铺垫。

1.2 实现分析

1.2.1 概图分析

spring 采用的是面向接口编程,原因是更加灵活,方法中参数为接口类型,那么只需要传入该接口的实现类,可以更好的去拓展业务。

1.2.2 静态代理是什么?

Java中的静态代理要求代理类(ProxySubject)和委托类(RealSubject)都实现同一个接口(Subject)。静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时动态生成,静态代理的效率相对动态代理来说相对高一些,但是静态代理代码冗余大,一单需要修改接口,代理类和委托类都需要修改。

购买业务接口:图书购买和商品购买类实现该接口。

切面AOP接口:事务和日志类实现该接口。

代理对象Agent :代理的是购买业务。

委托类:BookServiceImpl 、ProductServiceImpl

代理类 : Agent

2.1 实现过程

Service接口

package cn.itxiaoli;

/**
 * @author itxiaoli
 * @className Service
 * @description:
 * @date 2022/4/10 21:01
 */

public interface Service {
    void buy();
}

BookServiceImpl 实现类

package cn.itxiaoli;

/**
 * @author itxiaoli
 * @className BookServiceImpl
 * @description:
 * @date 2022/4/10 21:01
 */
public class BookServiceImpl implements Service {
    @Override
    public void buy() {
        System.out.println("图书购买");
    }
}

ProductServiceImpl 实现类

package cn.itxiaoli;

/**
 * @author itxiaoli
 * @className ProductServiceImple
 * @description:
 * @date 2022/4/10 21:01
 */
public class ProductServiceImpl implements Service {
    @Override
    public void buy() {
        System.out.println("商品购买");
    }
}

Aop 切面接口

package cn.itxiaoli;

/**
 * @author itxiaoli
 * @className Aop
 * @description:
 * @date 2022/4/10 21:02
 */

public interface Aop {

    default void before() {
    }

    default void after() {
    }

    default void exception() {
    }
}

Aop 接口中用 default 关键字来修饰,作用是默认空实现,实现类实现该接口时,不需要强制全部重写,根据需求来指定对应方法的重写,如LogAop日志接口,只重写了before(),其他方法空实现了。

LogAop 实现类

package cn.itxiaoli;

/**
 * @author itxiaoli
 * @className RizhiAop
 * @description:
 * @date 2022/4/10 21:17
 */
public class LogAop implements Aop {
    @Override
    public void before() {
        System.out.println("日志执行....");
    }
}

TransactionAop 实现类

package cn.itxiaoli;

/**
 * @author itxiaoli
 * @className ShiwuAop
 * @description:
 * @date 2022/4/10 21:18
 */
public class TransactionAop implements Aop {
    @Override
    public void before() {
        System.out.println("事务开启");
    }

    @Override
    public void after() {
        System.out.println("事务提交");
    }

    @Override
    public void exception() {
        System.out.println("事务回滚");
    }
}

代理类

package cn.itxiaoli;

/**
 * @author itxiaoli
 * @className Agent
 * @description:
 * @date 2022/4/10 21:07
 */
public class Agent implements Service {
    private Service target;
    private Aop aop;
    
    public Agent(Service target, Aop aop) {
        this.target = target;
        this.aop = aop;
    }
    
    @Override
    public void buy() {
        try {
            // 切面
            aop.before();
            // 执行业务逻辑
            target.buy();
            // 切面
            aop.after();
        } catch (Exception e) {
            // 切面
            aop.exception();
            e.printStackTrace();
        }

    }
}

测试类

package cn.itxiaoli;

import org.junit.Test;

/**
 * Unit test for simple App.
 */
public class AppTest {

    /**
     * Rigorous Test :-)
     */
    @Test
    public void TestAop() {
        Agent agent = new Agent(new BookServiceImpl(), new LogAop());
        agent.buy();
        System.out.println("==========agent2=======");
        Agent agent2 = new Agent(new ProductServiceImpl(), new TransactionAop());
        agent2.buy();
        System.out.println("=========agent3========");
        Agent agent3 = new Agent(agent2, new LogAop());
        agent3.buy();
    }
}

控制台agent3中在事务切面开启时,首先执行了日志切面,达到了嵌套事务,增强业务功能。原因是Agent类也实现了购买接口中的buy()方法,所以new Agent()中的第一个参数为实现购买接口的实现类对象,是多态的体现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值