1.什么是应用框架(application framework)
个人认为,应用框架是软件开发中一组可重用的设计和代码。他是我们所开发的应用系统的支撑骨架,一种基本结构。而结构(structure)就是框架的本质。在我们的开发一个比较复杂的应用系统的过程中,我们会发现我们要实现的应用包含了非常多不断变化的东西,从而让我们难以把握他们之间的复杂关系。而通过结构,我们可以把这些不断变化的东西,组织成易于理解的少数几个主要部分。
应用框架为我们提供了结构和模板(模板本身也是一种结构),我们以此为基础来构建我们的应用系统。这样的一个应用框架,通常都是由一些抽象类,具体类和类之间的预定义的交互行为,规则来构成的。而我们就可以重用这些由框架提供的代码和设计。
2.应用框架的优点
(1)模块化 (2)可重用性 (3)易于扩展 (4)可维护 (5)简单性(隐藏复杂细节)
3.应用框架包含的提供的通用服务(功能)
(1)配置管理服务 (2)IOC容器 (3)缓存服务 (4)事件通知服务 (5)"Windows 服务" (6)消息队列
(7)身份验证服务 (8)授权服务 (9)文档管理 (10)事务管理 (11)工作流 (12)加密/解密
(13)日志管理 (14)异常管理 (15)脚本支持(16) 资源管理(17)数据访问,O/R Mapping
(18)License管理
什么是一个好的设计?我想要做一个好的设计,有这么几个挑战。
1。对象的职责的定义和划分
2。可扩展性
3。可重用性
1. 明确定义和划分对象的职责。也就是说一个class,他应该专注于做很少的功能,而不是面面具到,无所不能。通过class的名称和方法,我们可以很清楚这个class到底提供什么样的功能和职责。说起来很简单,可是实际做起来,还是很困难的。
2. 可扩展性。我的设计如何才可以做到,在需求发生变化后,在新的组件和服务产生后,我可以在不改动原有设计而把新的东西集成进来。在我替换和修改了已有组件的实现后,依赖他的上层的代码不需要做任何的改动。
3. 可重用性。对象之间的依赖关系复杂。如和在一个新的项目里重用以前已经实现的class,在我们现在的开发过程里,通常都是一个复杂的过程。
如果解决这三个难题呢。我认为,IOC为我们提供了解决这3个难题的途径。
IOC,英文是Inversion of Control
,中文翻译为“控制反转”。用于对调用和被调用者之间进行解耦。
//
The contract
public
interface
IEmailSender
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
{
void Send(String from, String to, String message)
}
//
The implementation
public
class
SmtpEmailSender : IEmailSender
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
{
private String _host;
private int _port;
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
public SmtpEmailSender(String host, int port)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
_host = host;
_port = port;
}
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
public void Send(String from, String to, String message)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
// Configures the Smtp class and sends the e-mail
}
}
public
interface
ITemplateEngine
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
{
String Process(String templateName)
}
光这样一个ITemplateEngine还不够,我们还需要一个组件来负责执行模板转换和分发邮件的功能。
public
interface
INewsletterService
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
{
void Dispatch(String from, String[] targets, String messageTypeName)
}
这是一个很简单的类,只有寥寥数行的代码。也许我们在自己的开发过程中,会经常看到类似的代码。可是就这寥寥数行代码里面,仍然有一些问题存在。
1. 代码里是通过ConfigurationSettings来获得配置信息。如果我们变更Configuration的存储形式,或者用其他的xml文件存储,或者是存储在数据库,或者是从远端的webservice里获得配置信息,代码就不得不做出修改,重新编译。
2. 这class所担负的职责要比他的名字所描述的要多。这个类提供发送邮件的功能,但是,不仅仅与此,这个类还会调用一个template 引擎对邮件的文本进行处理。由此带来的另外一个问题就是,这个类必须具备对这个template 引擎的知识,知道如何调用这个引擎的方法。
这样的2个主要问题带来的影响就是,给这个类增加了两个比较强的依赖关系。就是对外部config模块和邮件template 引擎的依赖。也许有人会觉得,这没有什么问题呀,我们平时写代码也是这样的,没有什么不好呀。可是仔细考虑一下,如果需求变动,config部分变更,配置的Key发生变化,或者配置从另外的xml获取,或者配置从Database获取,或者配置是从一个webService获取,那么上面的这段代码无疑就要进行修改。如果这样的地方多了,那修改起来既容易错,又容易发生漏改。再说template引擎,如果我们换了另外一个模板引擎,我们也需要类似的做修改。
从另外一个角度说,如果我们又有了一个类似的项目,里面也有发邮件的功能。通常,最快的方法就是把这些代码copy过来,做少量的修改。但是,这个并不是一个好的,高效的做饭。同时,代码的维护也变得多出了一倍。这里,又引入了一个我们在框架设计是的一个思想,就是组件化,服务化。而IOC容器就提供了一种手段和工具来帮助我们管理这些组件和服务。
什么是组件呢?我个人认为,组件就是一小段可重用的代码单元。对外部,他应该提供一个职责明确的服务接口,也就是说,这个组件只处理他职责范围内的事情,并且要处理得很好。通常来说,一个组件就是一个Class,实现了一个Service,也就是实现了一个interface。而这个interface就为我们引入了一个抽象层,把接口服务和实现分开。即我们常说的面向接口的开发。
再回到刚才的例子。
我们先定义Email的service
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a40f0ce42122f34a6efdfe783c695216.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0aff146880e347d7c463faabc72ba80b.gif)
这个接口描述了发送Email这个Service的契约,只要实现了这个契约所规定的,不管是用smtp,还是IMAP或者其他的什么的,我们都认为是合法的。
OK
,接下来我们给契约增加一个实现,使用
smpt
来访发送邮件。
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a40f0ce42122f34a6efdfe783c695216.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0aff146880e347d7c463faabc72ba80b.gif)
看起来,是不是感觉这样做好了一些。现在这个类就只负责把邮件发送出去,并不负责对邮件的文本进行模板处理。
OK,我们再定义一个邮件Template的接口:
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a40f0ce42122f34a6efdfe783c695216.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0aff146880e347d7c463faabc72ba80b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a40f0ce42122f34a6efdfe783c695216.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0aff146880e347d7c463faabc72ba80b.gif)
OK
,现在让我们来考虑一下
INewsletterService
接口服务应该如何实现。很显然,需要使用
IEmailSender
服务
和
ITemplateEngine
服务,而不用关系
IEmailSender
和
ITemplateEngine
的具体实现是如何。
public
class
SimpleNewsletterService : INewsletterService
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
{
private IEmailSender _sender;
private ITemplateEngine _templateEngine;
public SimpleNewsletterService(IEmailSender sender,
ITemplateEngine templateEngine)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
_sender = sender;
_templateEngine = templateEngine;
}
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
public void Dispatch(String from, String[] targets, String messageTypeName)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
String message = _templateEngine.Process(messageTypeName);
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
foreach(String target in targets)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
_sender.Send(from, target, message);
}
}
}
IWindsorContainer container
=
new
WindsorContainer();
container.AddComponent(
"
newsletter
"
,
typeof
(INewsletterService),
typeof
(SimpleNewsletterService) );
container.AddComponent(
"
smtpemailsender
"
,
typeof
(IEmailSender),
typeof
(SmtpEmailSender) );
container.AddComponent(
"
templateengine
"
,
typeof
(ITemplateEngine),
typeof
(NVelocityTemplateEngine) );
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
//
Ok, start the show
INewsletterService service
=
(INewsletterService) container[
"
newsletter
"
];
service.Dispatch(
"
hammett at gmail dot com
"
, friendsList,
"
merryxmas
"
);
public
class
SmtpEmailSender : IEmailSender
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
{
private String _host;
private int _port;
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
public SmtpEmailSender()
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
_host = "mydefaulthost";
_port = 110; // default port
}
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
public String Host
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
get
{ return _host; }
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
set
{ _host = value; }
}
public int Port
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
get
{ return _port; }
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
set
{ _port = value; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
//![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
}
<?
xml version="1.0" encoding="utf-8"
?>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
configuration
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
configSections
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
section
name
="castle"
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
type
="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
Castle.Windsor"
/>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
</
configSections
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
castle
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
components
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
component
id
="smtpemailsender"
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
parameters
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
host
>
localhost
</
host
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
<
port
>
110
</
port
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
</
parameters
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
</
component
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
</
components
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
</
castle
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
</
configuration
>
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a40f0ce42122f34a6efdfe783c695216.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0aff146880e347d7c463faabc72ba80b.gif)
现在看上去,是不是感觉好了很多。通过设计上的重构,良好定义对象的职责,这段代码已经变得比以前更加灵活和易于扩展了。但是,仍然有个问题存在。我们需要自己把所有有关的东西联系起来,包括IEmailSender, ITemplateEngine, 然后把他们传递到INewsletterService。
这些我们是可以手工通过代码来完成,但是,借助于IOC容器,我们可以使用另外一种方式来完成同样的功能。
接下来,我以.net下的开源IOC框架Castle为例子来说明IOC容器的神奇之处。
下面这段代码,就可以完成我们上面的功能
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
OK,让我来解释一下,上面的这段代码里到底是如何发挥这神奇功效的。
1. 首先,在容器里注册INewsletterService 服务,并指定服务的实现是SimpleNewsletterService,服务在容器内的索引Key是newsletter
2. 在容器里注册IEmailSender服务,并指定IEmailSender的实现是SmtpEmailSender,服务在容器内的索引Key是smtpemailsender。容器会检查SmtpEmailSender类,发现他只有一个带参数的构造函数SmtpEmailSender(String host, int port),而host和port目前还无法获得,这个我们在后面会对SmtpEmailSender修改一下,来修正这个问题。
3. 在容器里注册ITemplateEngine服务,并指定ITemplateEngine的实现是NVelocityTemplateEngine,服务在容器内的索引Key是templateengine
4. 容器检测SimpleNewsletterService,发现他的构造函数需要IEmailSender和ITemplateEngine,容器会先创建 IEmailSender和ITemplateEngine的实例,然后再创建出SimpleNewsletterService实例。
首先我们修改
SmtpEmailSender
的实现,以适应容器。
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a40f0ce42122f34a6efdfe783c695216.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0aff146880e347d7c463faabc72ba80b.gif)
如上所示,我们提供了一个无参数的构造函数,并且提供了两个属性Host和Port。这样容器可以创建一个SmtpEmailSender,并且通过读取配置,来设置Host和Port。
一个简单的配置文件的例子如下:
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
这样,容器替我们完成了创建组件的任务。容器可以检测容器内的组件的相互依赖性,并且可以通过外部的配置文件来配置容器的实现,设置其属性。
本质上来说,容器帮我们把组件之前的耦合性转移到容器外的配置文件里。但是组件之间的依赖性是通过接口来弱化的,就只是一个松耦合的关系。
当然,容器的作用不仅仅与此,我们还可以为同一个服务指定多个实现,通过配置,可以指定被依赖的服务采用何种实现,可以为指定的组件定制自己ComponentActivator来控制其创建过程。还可以通过动态代理的方式,完成一些面向方面的特殊功能。
总之,
IOC
容器是非常强大的工具,是我们框架的基础与核心,为框架的可扩充提供了必备的条件
首先我们从解耦这个方面来讨论。
对组件之间的关系进行解耦,通常我们需要处理的情况有2种:1。获取外部的配置信息 2
。获取一个组件对象的引用。举个例子来说明一下:
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cee29d823755a7f0635450c80fa6ad56.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/790fcecb321590905fab39f9d17b193b.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a40f0ce42122f34a6efdfe783c695216.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/52027445fc0a19b9c039aed50f2fe9b5.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/70f6a658c73bd2f4a825c90eb4d9f5b4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/27b77279fa29dd757f55ab54b70b907a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/29c950173457e1a472cb734fe67fabf1.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0aff146880e347d7c463faabc72ba80b.gif)