Baidu 写道
约定优于配置(Convention Over Configuration)
约定优于配置是一个简单的概念。 系统,类库,框架应该假定合理的默认值,而非要求提供不必要的配置。 流行的框架如 Ruby on Rails 和 EJB3 已经开始坚持这些原则,以对像原始的 EJB 2.1 规范那样的框架的配置复杂度做出反应。 一个约定优于配置的例子就像 EJB3 持久化,将一个 特殊的Bean持久化,你所需要做的只是将这个类标注为 @Entity 。 框架将会假定表名和列名是基于类名和属性名。 系统也提供了一些钩子,当有需要的时候你可以重写这些名字,但是,在大部分情况下,你会发现使用框架提供的默认值会让你的项目运行的更快。
上午闲暇的时候,开发了一个简单的基于Coc策略的对象工厂。目的是验证一下Coc的基本实现逻辑.
因为Coc是一种比较好的简单化DI实现、配置和维护的好方式,虽然它代替不了XML来说明依赖关系,因为对于值类型注入
和接口注入它还无能为力,但是为大大简化DI的实现、配置以及维护提供很好的改进,实际中应该将Coc和XML声明的方式
结合起来使用。下面是我写的一个简单的实现,不过后期将不断改善和丰富。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
namespace DotNetConsole
{
public delegate void InitObjectRelationShip (object thisObj);
public class ObjectFactory
{
private static Random NextObj = null;
public static object Create (Type ObjectType, InitObjectRelationShip InitMethod)
{
object CachedObject = CreateObject (ObjectType, InitMethod);
if (NextObj == null)
NextObj = new Random ();
if (ObjectPoolService.GetCahce ().ContainsKey (ObjectType.ToString ())) {
ObjectPoolService.SetCurrentPoolInUse (true);
if (ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Count < ObjectPoolService.GetMaxSize ()) {
ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Add (CachedObject);
}
int index = (int)NextObj.Next (ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Count);
return ObjectPoolService.GetCahce ()[ObjectType.ToString ()][index];
} else {
if (ObjectPoolService.GetMaxSize () > ZERO_VALUE) {
ObjectPoolService.SetCurrentPoolInUse (true);
ObjectPoolService.GetCahce ().Add (ObjectType.ToString (), new List<object> ());
ObjectPoolService.GetCahce ()[ObjectType.ToString ()].Add (CachedObject);
}
}
ObjectPoolService.SetCurrentPoolInUse (false);
return CachedObject;
}
///in the future ,will implement proxy object not real object and
///base on proxy way, for object's method calling will be done as parall way.
private static object CreateObject (Type ObjectType, InitObjectRelationShip InitMethodDef)
{
object FirstHeadObject = Activator.CreateInstance (ObjectType);
if (InitMethodDef == null) {
Type[] interfaceTypes = ObjectType.GetInterfaces ();
if (interfaceTypes.Length != 0) {
foreach (Type interfaceSubType in interfaceTypes) {
if (interfaceSubType.Equals (typeof(IUserModeObjectInitor))) {
((IUserModeObjectInitor)FirstHeadObject).Init ();
}
}
}
PropertyInfo[] proInfos = ObjectType.GetProperties ();
if (proInfos.Length != 0) {
foreach (PropertyInfo pro in proInfos) {
if (pro.GetValue (FirstHeadObject, null) == null) {
SetDepthObjectRelationShip (FirstHeadObject, pro);
}
}
}
} else {
InitMethodDef (FirstHeadObject);
}
return FirstHeadObject;
}
private static void SetDepthObjectRelationShip (object MainObject, PropertyInfo PropertyType)
{
object PropertyObject = Activator.CreateInstance (PropertyType.PropertyType);
PropertyType.GetSetMethod ().Invoke (MainObject, new object[] { PropertyObject });
PropertyInfo[] innerProps = PropertyType.PropertyType.GetProperties ();
if (innerProps.Length != 0) {
foreach (PropertyInfo innerProerty in innerProps) {
SetDepthObjectRelationShip (PropertyObject, innerProerty);
}
}
}
private const int ZERO_VALUE = 0;
}
}
在ObjectFactory中,还使用了一个基于无状态对象的ObjectPoolService(实现在下面,暂时提供最简单的实现),目的是提供对象重用率减少内存占用有量,并且提供随机的对象获取机制,因为客户程序不关心同一类型的多个对象哪一个为其提供服务。并且在MaxSize=0时,可以不使用ObjectPoolService而直接Create Object. MaxSize越大,Pool中某一个对象的重用机会就越小,并且内存占用率也比较高,所以MaxSize可以用来微调内存占有率和重用几率的配置。
值得注意的是Create方法中提供一个类型为
InitObjectRelationShip
的委托参数,它可以由调用者指定对象关系组装的方式(如果不想使用Coc的话,或者结合XML配置和Coc的话,可以看一下下面的测试代码),组合各种DI策略就比较灵活了.
另外还设计了一个叫做IUserModeObjectInitor的接口,用于跳过组装过程,开发者自己组装对象关系,但是侵入性比较强,
建议使用ObjectFactory的Create方法中的委托参数干这件事情,这里保留这个接口的目的是为了方式灵活,不过以方法的委托参数的处理为优先!
using System;
namespace DotNetConsole
{
public interface IUserModeObjectInitor
{
void Init();
}
}
为了提高性能,还设计了一个极为简单的Cache:
using System;
using System.Collections.Generic;
namespace DotNetConsole
{
//use cassanadra db repleace in the future.
public class ObjectPoolService
{
private static volatile Dictionary<string,List<object>> m_ObjectCache=null;
private static int m_MaxSize=0;
private static bool m_IsInUse=false;
public static Dictionary<string, List<object>> GetCahce ()
{
if (m_ObjectCache == null)
m_ObjectCache = new Dictionary<string, List<object>> ();
return m_ObjectCache;
}
public static void SetMaxSize (int Size)
{
m_MaxSize = Size;
}
public static int GetMaxSize ()
{
return m_MaxSize;
}
public static void SetCurrentPoolInUse (bool isInUse)
{
m_IsInUse = isInUse;
}
public static bool GetCurrentPoolUsingState ()
{
return m_IsInUse;
}
public static void ShutdownPool ()
{
if (!m_IsInUse)
{
m_ObjectCache.Clear ();
}
}
}
}
测试的代码:
using System;
using System.Reflection;
namespace DotNetConsole
{
class MainClass
{
//statefulless Object gen! can reduce mem.
public static void Main (string[] args)
{
ObjectPoolService.SetMaxSize (100);
double timestart = DateTime.Now.Millisecond;
((OrderService)ObjectFactory.Create (typeof(OrderService), x =>
((OrderService)x).DAOObject = (OrderDAO)ObjectFactory.Create (typeof(OrderDAO), null))).ShowInfo ();
for (int i = 0; i < 1000; i++)
{
((OrderService)ObjectFactory.Create (typeof(OrderService), null)).ShowInfo ();
}
ObjectPoolService.SetCurrentPoolInUse (false);
ObjectPoolService.ShutdownPool ();
double timeend= DateTime.Now.Millisecond;
Console.WriteLine (timeend-timestart);
Console.ReadLine();
}
}
}
以上,基本思路就是先排除用XML来定义类之间的依赖关系,当前先暂时开发一个最基本的只有基于Coc策略的基本对象工厂,实现方式很简单,就是利用反射获取目标类型的属性列表,然后取得属性的类型(暂时只是引用类型),然后还是利用反射实例化对应属性类型的对象并注入到目标对象中,然后递归地这样处理,所有依赖的对象都初始化并组装进来。
当然这是一个最基本的实现。基于这个在考虑拓展,是比较好的方式,逐步演化比较好。后续还有很多工作要做,
处理这个简单的工厂,必须以此为基础开发达到能使用级别的分布式对象Cache、分布式的层次型的Object容器、基于代理的对象创建、AOP、由于要采用Emit来创建代理对象的方式来实现基于代理的类型创建,然后将此”虚拟“出来的类型传给这个ObjectFactory来生成对象,那么有可能在“虚拟”出来的类型(代理)中插入任何想干的事情,比如前面的AOP或者只有在调用一个方法时在实例化目标“能干活”的真实对象(延迟加载),另外能够将代理类用Emit伪装成WCF的服务类型(插入服务契约等Attribute等),那么就可以实现对象服务的发出(向网络公布成服务)的功能,以上这些增强,我会逐步加入,都是以当前这个ObjectFactory作为最底层的基础的。后续的改进代码会陆续登录上来的
分享到:
相关推荐
Struts2约定优于配置 Action路径到Result页面路径的自动映射
ActiveModel::Serializer 给你带来约定优于配置JSON生成
基于Java的快速建站框架实现。...并大量使用Java5中的Annotation、Enum、Generic等众多新特性,遵循“约定优于配置的原则”,最大程度上的减少了配置文件的数量,甚至可以实现零配置完成系统的开发。
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
基于Maven、springMVC、Hibernate、FreeMarker注解的敏捷型快速开发框架,深度贯彻COC(Convention Over Configuration)约定优于配置思想,具有类似于Ruby on Rails的架构风格和开发效率,遵循LGPL开源协议。
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...