基于spring的动态代理模式示例 - JDK与CGLIB

代理模式示例:商店shop为实际购物地点,骑手rider为代理

JDK动态代理

特点:基于接口的代理,被代理的方法必须是接口中的方法

商店接口

/**
 * 商店接口
 */
public interface IShopService {
    /**
     * 购物方法
     * @param commodityName 商品名
     * @return 购物结果
     */
    String trade(String commodityName);
}

实现类

/**
 * 商店实现类
 */
@Service
public class ShopServiceImpl implements IShopService {
    /**
     * 购物方法
     * @param commodityName 商品名
     * @return 购物结果
     */
    @Override
    public String trade(String commodityName) {
        System.out.println("商店出售商品: "+commodityName);
        return "商店出售商品:"+ commodityName;
    }
}

创建JDK动态代理对象

/**
 * JDK动态代理工厂
 */
@Configuration
public class ProxyFactory {
    /**
     * spring容器中的商店实现类
     */
    @Autowired
    private IShopService shopService;

    /**
     * 代理工厂创建一个代理(骑手)并注入容器
     * @return 代理(骑手)
     */
    @Bean(name = "rider")
    public IShopService getProxyRider() {
        // 创建一个代理对象
        IShopService rider = (IShopService) Proxy.newProxyInstance(
                shopService.getClass().getClassLoader()
                , shopService.getClass().getInterfaces()
                , new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 前置通知
                        System.out.println("骑手正在去商店的路上...");
                        // 具体实现
                        Object commodity = method.invoke(shopService, args);
                        // 后置通知
                        System.out.println("骑手已购买到商品,正在送货...");
                        // 执行结果
                        return commodity;
                    }
                });
        return rider;
    }
}

测试controller

/**
 * 购物控制器
 */
@RestController
@RequestMapping("/shopping")
public class ShoppingController {
    /**
     * 商店实现类
     */
    @Resource(name = "shopServiceImpl")
    private IShopService shopService;
    /**
     * 代理(骑手)
     */
    @Resource(name = "rider")
    private IShopService rider;

    /**
     * 直接从商店购买
     * @param commodityName 商品名
     * @return 购买结果
     */
    @GetMapping("/shop/{commodityName}")
    public String buyCommodityByShop(@PathVariable(value = "commodityName") String commodityName){
        return shopService.trade(commodityName);
    }

    /**
     * 骑手代理购买
     * @param commodityName 商品名
     * @return 购买结果
     */
    @GetMapping("/rider/{commodityName}")
    public String buyCommodityByRider(@PathVariable(value = "commodityName") String commodityName){
        return rider.trade(commodityName);
    }
}

测试结果

http://localhost:8080/shopping/rider/奶茶
测试结果

CGLIB动态代理

特点:基于继承的代理,没有接口也可代理,但被代理的类与方法不能被final修饰

商店实现类(没有接口)

/**
 * 商店实现类
 */
@Service("shopService")
public class ShopService {
    /**
     * 购物方法
     * @param commodityName 商品名
     * @return 购物结果
     */
    public String trade(String commodityName) {
        System.out.println("商店出售商品: "+commodityName);
        return "商店出售商品:"+ commodityName;
    }
}

创建CGLIB动态代理对象

/**
 * CGLIB动态代理工厂
 */
@Configuration
public class ProxyFactory implements MethodInterceptor {

    /** 
     * 代理工厂创建一个代理(骑手)并注入容器
     * @return 代理(骑手)
     */
    @Bean(name = "rider")
    public ShopService getProxyRider() {
        // 创建enhancer对象
        Enhancer enhancer = new Enhancer();
        // 设置要代理(继承)的类
        enhancer.setSuperclass(ShopService.class);
        // 设置回调方法,即代理方法
        enhancer.setCallback(this);
        // 创建代理类
        ShopService rider = (ShopService) enhancer.create();
        // 注入spring容器
        return rider;
    }

    /**
     * 具体的代理逻辑
     * @param o 被代理的对象
     * @param method 被代理的方法
     * @param objects 方法参数
     * @param methodProxy 方法代理工具类
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 前置通知
        System.out.println("骑手正在去商店的路上...");
        // 具体实现
        Object commodity = methodProxy.invokeSuper(o, objects);
        // 后置通知
        System.out.println("骑手已购买到商品,正在送货...");
        // 执行结果
        return commodity;
    }
}

测试controller

@RestController
@RequestMapping("/shopping")
public class ShoppingController {
    /**
     * 商店实现类
     */
    @Resource(name = "shopService")
    private ShopService shopService;
    /**
     * 代理(骑手)
     */
    @Resource(name = "rider")
    private ShopService rider;

    /**
     * 直接从商店购买
     * @param commodityName 商品名
     * @return 购买结果
     */
    @GetMapping("/shop/{commodityName}")
    public String buyCommodityByShop(@PathVariable(value = "commodityName") String commodityName){
        return shopService.trade(commodityName);
    }

    /**
     * 骑手代理购买
     * @param commodityName 商品名
     * @return 购买结果
     */
    @GetMapping("/rider/{commodityName}")
    public String buyCommodityByRider(@PathVariable(value = "commodityName") String commodityName){
        return rider.trade(commodityName);
    }
}

测试结果

http://localhost:8080/shopping/rider/可乐
代理测试结果

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值