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 提供了一个名为 Convention 的插件,可以实现约定优于配置。 Convention 插件需要 struts2-convention-plugin-2.2.1.jar 这个 jar 包。 ### 设置 Convention 结果路径 Convention 插件可以通过设置 ...
这个库遵循“约定优于配置”(Convention Over Configuration,简称CoC)的设计原则,这是Ruby on Rails框架的核心理念之一。它允许开发者在无需大量手动编写代码的情况下,自动处理模型数据转化为JSON格式的过程。 ...
BatMap是一个高效且易用的库,专门设计用于.NET平台,提供基于约定的映射功能,简化了开发人员在处理对象转换时的工作。 **一、 BatMap的核心特性** 1. **基于约定的映射**: BatMap遵循“约定优于配置”的原则,...
Rails 使用Web应用多年来积累的各种常见约定来代替XML配置文件,而在Rails内部的映射与发现机制根据这些约定可以实现对象之间的关联。这样可以减少代码量,降低bug的可能性,降低维护程序和升级程序的难度。 但是,...
它通过提供“约定优于配置”的方式,使得创建独立的、生产级别的基于 Spring 的应用程序变得异常简单。在 Spring Boot 中,我们可以通过 Java 配置来替代传统的 XML 配置,这极大地提高了代码的可读性和可维护性。 ...
Struts2是一个流行的Java Web应用程序...Convention Plugin是Struts2的一个插件,它基于“约定优于配置”的原则,自动地为Action类和结果页面建立映射,从而极大地减少了手动配置的需求。通过自动探测和推理,Conventio
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
CoC风格的核心理念是“约定优于配置”,即在没有明确配置的情况下,系统会遵循一套预定义的规则来自动处理任务。在Struts2中,这表现为框架自动处理Action、结果类型、拦截器等的配置,减少了XML配置文件的使用。...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
Maven的工作原理基于“约定优于配置”的原则。它有一个预定义的构建生命周期和一组标准的构建阶段,如clean、compile、test、package、install和deploy。每个阶段都对应一组插件目标,这些目标执行具体的构建任务。...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...
基于Maven、springMVC、Hibernate、FreeMarker注解的敏捷型快速开发框架,深度贯彻COC(Convention Over Configuration)约定优于配置思想,具有类似于Ruby on Rails的架构风格和开发效率,遵循LGPL开源协议。
本文详细介绍了如何基于SpringBoot框架设计并实现一个项目信息管理系统。文章首先对SpringBoot、Maven和Thymeleaf等关键技术进行了概述。随后,围绕系统设计方案进行了详细阐述,包括系统总体设计和数据库设计两个...
Spring Data JPA通过约定优于配置的原则,提供了丰富的默认实现,使得开发者只需要编写少量的自定义代码就可以完成数据操作。 知识点七:Thymeleaf模板引擎 Thymeleaf是一种现代的Java模板引擎,用于Web和独立环境...
Grosbeak充分利用Java 5的新特性,如Annotation、Enum和Generic,强调“约定优于配置”的原则,大大减少了配置文件的需求,甚至有可能实现零配置开发。 在选题背景中,报告提到了当前IT技术的快速发展和多样化的建...
约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一...