代理模式示例:商店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/可乐