什么是代理
代理就是给目标对象一个代理对象,并又代理对象控制目标的引用.
为什么使用代理模式
- 通过引入代理对象的方式,间接访问目标对象,避免不必要的复杂性.
- 通过代理对象可以对原有的业务实现增强.
举例:如果我们需要买国外的某一件商品A,这个时候我们一般有两个途径要么直接去国外买,要么可以找一些代购人员帮我们去购买。在这种情况下,我们由于直接去国外买,实在是太耗软妹币,而且还要花时间等等,这个时候我们最优的选择就是找代购购买,这样也帮我们省去了很多麻烦的事情。
代码示例
接口:
public interface ITargetFactoryService {
void sale(String name);
}
目标对象:
public class TargetFactoryServiceImpl implements ITargetFactoryService {
@Override
public void sale(String name) {
log.info(name+"购买了商品A");
}
}
代理对象:
public class ProxyImpl implements ITargetFactoryService {
public ITargetFactoryService service;
public ProxyImpl(ITargetFactoryService service){
super();
this.service = service;
}
@Override
public void sale(String name) {
before();
service.sale("代购");
after();
}
/**
* 后置增强
*/
private void after() {
log.info("代购在购买后得到了市场调研结果");
}
/**
* 前置增强
*/
private void before() {
log.info("代购在购买前做了市场调研");
}
}
测试类:
public class SpsringJdbcApplication {
public static void main(String[] args) {
TargetFactoryServiceImpl service = new TargetFactoryServiceImpl();
ProxyImpl proxy = new ProxyImpl(service);
proxy.sale("代购");
SpringApplication.run(SpsringJdbcApplication.class, args);
}
}
测试结果:
通过示例可以看到,代理对象包含了目标对象,并且在业务处理上进行了一定的业务扩展,但却和目标对象继承于同一个接口.
这种情况便是静态代理,适合业务情况比较简单,实现类少,需求变化不频繁,但是要对原有目标服务对象进行功能扩展,并且不修改原有服务,这个时候我们可以选择使用静态代理.
静态代理的缺点
如果此时业务继续扩展,在经过一定的调研之后,发现商品B更加收欢迎,这个时候我们就需要对业务继续进行扩展.
接口
public interface ITargetFactoryBService {
void saleB(String name);
}
目标对象
public class ITargetFactoryBServiceImpl implements ITargetFactoryBService {
@Override
public void saleB(String name) {
log.info(name + "购买了商品B");
}
}
代理对象
public class ProxyTwoImpl implements ITargetFactoryService, ITargetFactoryBService {
public ITargetFactoryService service;
public ITargetFactoryBService bService;
public ProxyTwoImpl(ITargetFactoryService service,ITargetFactoryBService bService){
super();
this.service = service;
this.bService = bService;
}
@Override
public void sale(String name) {
before();
service.sale("代购");
after();
}
@Override
public void saleB(String name) {
before();
bService.saleB("代购");
after();
}
/**
* 后置增强
*/
private void after() {
log.info("代购在购买后得到了市场调研结果");
}
/**
* 前置增强
*/
private void before() {
log.info("代购在购买前做了市场调研");
}
}
测试类:
public class SpsringJdbcApplication {
public static void main(String[] args) {
TargetFactoryServiceImpl service = new TargetFactoryServiceImpl();
ITargetFactoryBServiceImpl bService = new ITargetFactoryBServiceImpl();
ProxyTwoImpl proxy2 = new ProxyTwoImpl(service, bService);
proxy2.sale("代购");
proxy2.saleB("代购");
SpringApplication.run(SpsringJdbcApplication.class, args);
}
}
测试结果:
在进行业务扩展时,需要对原有的代理类进行修改,如果后期需要更多的业务时,这个类将变得繁杂,大量的继承以及重写,牵一发而动全身,所以这种业务扩展性高,业务变化繁杂的情况不适合使用静态代理.
总结
- 违反Java设计模式开闭原则,即:程序对外扩展开放,对修改关闭.当要进行变更时,应该是新增代码来实现,而不是在原有代码上进行修改.
- 扩展性差.
- 可维护性差.
- 代码耦合度高.