分离xQ?Separation of Concerns : SOCQ是Ioc模式和AOP产生最原始动力Q通过功能分解可得到关注点Q这些关注可以是 lgComponents, 斚wAspects或服务Services?/p>
从GoF设计模式中,我们已经?fn)惯一U思维~程方式QInterface Driven Design 接口驱动Q接口驱动有很多好处Q可以提供不同灵zȝ子类实现Q增加代码稳定和健壮性等{,但是接口一定是需要实现的Q也是如下语句q早要执行:(x)
AInterface a = new AInterfaceImp();
AInterfaceImp是接口AInterface的一个子c,Ioc模式可以延缓接口的实玎ͼҎ(gu)需要实玎ͼ有个比喻Q接口如同空的模型套Q在必要Ӟ需要向模型套注石膏,q样才能成ؓ(f)一个模型实体,因此Q我们将Zؓ(f)控制接口的实现成?注射"?/p>
Ioc英文?Inversion of ControlQ即反{模式Q这里有著名的好莱坞理论Q你呆着别动Q到时我?x)找你?/p>
其实Ioc模式也是解决调用者和被调用者之间的一U关p,上述AInterface实现语句表明当前是在调用被调用者AInterfaceImpQ由于被调用者名U写入了(jin)调用者的代码中,q生了(jin)一个接口实现的原罪Q彼此联p,调用者和被调用者有紧密联系Q在UML中是用依?Dependency 表示?/p>
但是q种依赖在分d注的思维下是不可忍耐的Q必dԌ实现调用者和被调用者解耦,新的Ioc模式 Dependency Injection 模式由此产生?jin)?Dependency Injection模式是依赖注的意思,也就是将依赖先剥,然后在适当时候再注射q入?/p>
Ioc模式QDependency Injection模式Q有三种Q?/p>
W一U类?从JNDI或ServiceManager{获得被调用者,q里cMServiceLocator模式?1. EJB/J2EE
2. AvalonQApache的一个复杂用不多的目Q?
W二U类?使用JavaBeans的setterҎ(gu) 1. Spring Framework,
2. WebWork/XWork
W三U类?在构造方法中实现依赖 1. PicoContainer,
2. HiveMind
有过EJB开发经验的人都知道Q每个EJB的调用都需要通过JNDIL到工厂性质的Home接口Q在我的教程EJB是什么章节中Q我也是从依赖和工厂模式角度来阐qEJB的用?/p>
在通常传统情况下,Z(jin)实现调用者和被调用者解耦,分离Q一般是通过工厂模式实现的,下面通过比较工厂模式和Ioc模式不同Q加q解Ioc模式?/p>
工厂模式和Ioc
假设有两个类B ?CQB作ؓ(f)调用者,C是被调用者,在B代码中存在对C的调用:(x)
public class B{
private C comp;
......
}
实现comp实例有两U途径Q单态工厂模式和Ioc?/p>
工厂模式实现如下Q?/p>
public class B{
private C comp;
private final static MyFactory myFactory = MyFactory.getInstance();
public B(){
this.comp = myFactory.createInstanceOfC();
}
public void someMethod(){
this.comp.sayHello();
}
......
}
特点Q?/p>
每次q行ӞMyFactory可根据配|文件XML中定义的C子类实现Q通过createInstanceOfC()生成C的具体实例?
使用Ioc依赖性注? Dependency Injection )实现Picocontainer如下QBcd同通常POJOc,如下Q?/p>
public class B{
private C comp;
public B(C comp){
this.comp = comp;
}
public void someMethod(){
this.comp.sayHello();
}
......
}
假设C接口/cL有一个具体实现CImpcR当客户端调用BӞ使用下列代码Q?/p>
public class client{
public static void main( String[] args ) {
DefaultPicoContainer container = new DefaultPicoContainer();
container.registerComponentImplementation(CImp.class);
container.registerComponentImplementation(B.class);
B b = (B) container.getComponentInstance(B.class);
b.someMethod();
}
}
因此Q当客户端调用BӞ分别使用工厂模式和Ioc有不同的特点和区别:(x)
主要区别体现在Bcȝ代码Q如果用IocQ在BcM码中不需要嵌入Q何工厂模式等的代码,因ؓ(f)q些工厂模式其实q是与C有些间接的联p,q样Q用Iocd解耦了(jin)B和C之间的联pR?/p>
使用Ioc带来的代hQ需要在客户端或其它某处q行B和C之间联系的组装?/p>
所以,Iocq没有消除B和C之间q样的联p,只是转移?jin)这U联pR?br /> q种联系转移实际也是一U分d注,它的影响巨大Q它提供?jin)AOP实现的可能?/p>
Ioc和AOP
AOP我们已经知道是一U面向切面的~程方式Q由于Ioc解放自由?jin)Bc,而且可以向B(ti)cd现注Ccd体实玎ͼ如果把BcL像成q行时的横向动作Q无疑注入Ccdcd是AOP中的一UAdvice
通过下列代码说明如何使用Picocontainer实现AOPQ该例程主要实现是记录logger功能Q通过Picocontainer可以使用单一行,使所有的应用cȝ记录功能ȀzR?/p>
首先~制一个记录接口:(x)
public interface Logging {
public void enableLogging(Log log);
}
有一个LogSwitcherc,主要用来Ȁzd体应用中的记录功能:(x)
import org.apache.commons.logging.Log;
public class LogSwitcher
{
protected Log m_log;
public void enableLogging(Log log) {
m_log = log;
m_log.info("Logging Enabled");
}
}
一般的普通应用JavaBeans都可以承这个类Q假设PicoUserManager是一个用L(fng)理类Q代码如下:(x)
public class PicoUserManager extends LogSwitcher
{
..... //用户理功能
}
public class PicoXXXX1Manager extends LogSwitcher
{
..... //业务功能
}
public class PicoXXXX2Manager extends LogSwitcher
{
..... //业务功能
}
注意LogSwitcher中Log实例是由外界赋予的,也就是说卛_被外界注进入,下面看看使用Picocontainer是如何注Log的具体实例的?/p>
DefaultPicoContainer container = new DefaultPicoContainer();
container.registerComponentImplementation(PicoUserManager.class);
container.registerComponentImplementation(PicoXXXX1Manager.class);
container.registerComponentImplementation(PicoXXXX2Manager.class);
.....
Logging logging = (Logging) container.getComponentMulticaster();
logging.enableLogging(new SimpleLog("pico"));//Ȁzlog
׃代码可见Q通过使用单一行logging.enableLogging()Ҏ(gu)使所有的应用cȝ记录功能ȀzR这是不是类似AOP的advice实现Q?/p>
MQ用Ioc模式Q可以不将来具体实玎ͼ完全在一个抽象层ơ进行描q和技术架构,因此QIoc模式可以为容器、框架之cȝ软g实现提供?jin)具体的实现手段Q属于架构技术中一U重要的模式应用?/p>