270 likes | 510 Views
Spring.Net v1.1 Quick Guide. ㈜ 중외정보기술 권효중. Inversion of Control. AOP. Data Access. Web Service. Overview. Sample. 2. 3. 4. 5. 1. 6. 목 차. 본 문서의 목적. 본 문서는 Spring.Net 프레임웍에 대한 사용자 가이드 역할을 합니다 .
E N D
Spring.Net v1.1 Quick Guide ㈜중외정보기술 권효중
Inversion of Control AOP Data Access Web Service Overview Sample 2 3 4 5 1 6 목 차
본 문서의 목적 본 문서는 Spring.Net 프레임웍에 대한 사용자 가이드 역할을 합니다. 닷넷 기반 어플리케이션 구축에 필요한 Spring.Net의 기능들 중 가장 널리 쓰이는 기능들을 중심으로 실제 예제와 함께 설명하여 어플리케이션 구축시 Spring.Net을 쉽게 적용할 수 있도록함이 본 문서의 목적입니다. 본 문서는 작성자의 Spring.Net 프레임웍에 대한 이해에 기반하므로 오류가 있을 수 있음을 밝혀두며, 발견한 오류를 작성자 메일로 보내주시면 즉시 수정토록 하겠습니다. 수정 이력
1. Overview • 1. Spring.Net의 목적 및 배경 • : 스프링닷넷을 한마디로 정의하자면 제어의 역전(Inversion of Control)을 기반으로한 닷넷 기반 엔터프라이즈 어플리케이션을 구축하기 위한 어플리케이션 프레임웍이라고 할 수 있다. • IoC, AOP의 기반하에 실행되는 특성으로 인해 여타 다른 어플리케이션 프레임웍과는 달리 추가되는 라이브러리나 컴포넌트들과 유연하게 작동될 수 있으며, 스프링닷넷의 궁극적인 목적은 세세한 기능을 지원해 주는 라이브러리 성격의 프레임웍이 아닌 엔터프라이즈 어플리케이션 전체에 아키텍쳐를 견고하게 구축해주는 뼈대 역할을 하는 것이다. • 위의 그림에서 보듯이 스프링닷넷은 IoC, AOP의 기반위에 Web, Data Access, ORM, Service 기능을 지원하고 있다. • 스프링닷넷을 사용하는 목적과 그 효과는 다양하지만, 그 중에서도 레이어간의 느슨한 결합(Loose Coupling)을 통한 컴포넌트화의 극대화, 주관심사(Core Concerns)에만 집중할 수 있는 개발 환경 지원으로 인한 개발속도 향상이라고 할 수 있을 것이다. Aspected Oriented Programming (AOP) ORM Nhibernate, iBatis.Net others Web Dependency Injection for ASP.NET & Web Services Master Pages, Biderectional Data Binding, Localization Data Transaction Infrastructure ADO.NET support DAL support Services Windows Services Remoting Web Services COM+ Enterprise Services CORE Inversion of Control Container Supporting Utilities (Collections, Threading, Pooling)
1. Overview • 2. 설치 및 사용방법 • : 스프링닷넷의 공식 웹사이트는 http://www.springframework.net 이다. • 이곳에서 좌측 메뉴의 “Downloads”를 클릭해서 Sourceforge로 이동한후 최신 • 버전을 다운받아서 설치한다. • 2007년 10월 9일 현재 최신 버전은 “Spring.NET-1.1-RC1.exe”이다. • 설치한후 프로그램 목록에 보면 다음과 같이 설치되며 매뉴얼 문서, 예제 샘플이 제공된다. • 비쥬얼스튜디오에서 참조하는 방법은 아래와 같이 설치경로의 bin 폴더에 있는 라이브러리를 직접 참조하면 된다.
2. Inversion of Control • 1. IApplicationContext 인터페이스의 역할 및 Dependency Lookup • : Application Context는 Spring.Net에서 관리하는 객체의 생성과 소멸 등 일련의 작업을 하기 위한 컨테이너라고 볼 수 있다. • 예를 들어, Spring.Net 프레임웍에서 ExampleObject 라는 객체를 관리한다면 이 객체의 인스턴스는 Application Context라는 컨테이너에 키와 값의 쌍으로 저장되어 있으며 프로그램에서 ExampleObject 객체를 사용하려고 하면 Spring.Net 프레임웍은 해당하는 Application Context에서 키를 조회하여 값에 해당하는 인스턴스를 리턴하는 방식이다. • <configuration> • <configSections> • <sectionGroup name="spring"> • <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> • <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/> • </sectionGroup> • </configSections> • <spring> • <context> • <resource uri="config://spring/objects"/> • </context> • <objects xmlns="http://www.springframework.net"> • ... 사용할 객체 선언 ... • </objects> • </spring> • </configuration> • 윈폼이나 웹폼의 응용 프로그램 구성 파일에서 위와 같이 Application Context를 지정한 후, 프로그램에서는 아래와 같이 호출하여 사용한다. • IApplicationContext ctx = ContextRegistry.GetContext(); • IDAO dao = ctx.GetObject("dao") as IDAO; • 물론 Web.config나 App.config 파일외의 별도 XML 파일에서 관리하는 것도 역시 가능하다. 단, 이 경우 주의할 점은 Visual Studio에서 별도의 XML 파일 속성 중 빌드 작업 속성을 ‘포함 리소스’로 빌드해야만 파일을 인식할 수 있다. • 쉽게 생각하면, 결국 Application Context는 마치 어플리케이션 전체를 관할하는 전역 변수나 인스턴스와 같은 역할을 한다고도 볼 수 있다.
2. Inversion of Control • 2. 객체의 생성과 소멸 • : 스프링닷넷 컨테이너는 설정파일을 사용하여 객체를 생성할 수 있다. • <object id=“exampleObject” type=“Examples.ExampleObject, ExampleLibrary”/> • App.config나 web.config에서 위와 같이 선언하면 exampleObject가 생성된다. • id 어트리뷰트는 설정파일 내에서 사용할 객체의 이름이며, name 어트리뷰트도 동일한 기능을 한다. type 어트리뷰트에는 생성할 객체의 어셈블리 이름과 네임스페이스 경로를 기재하면 된다. • 단, 이 경우 ExampleObject는 아규먼트 없는 디폴트 생성자를 가지고 있어야 한다. • 객체의 생성과 소멸시 각각 호출되는 메소드를 정의할 수 있다. • <object id="dao" • type="MySpringSample_03.DAO, MySpringSample_03" • init-method="Init" • destroy-method="Finish“ • singleton="true“ • lazy-Init=“true”/> • 스프링닷넷 프레임웍에 의해 관리되는 객체들은 기본적으로 모두 Singleton 방식으로 생성된다. Singleton 방식으로 생성하지 않으려면 singleton="false“ 로 설정한다. 디폴트는 true이다. • 웬만한 객체들은 Singleton 방식으로 생성하는 것이 가급적 메모리의 사용을 줄이는 방법이 될 수 있을 것이다. • lazy-Init 속성은 객체를 생성할 때 어플리케이션 로드시에 생성하는 것이 아니라 객체가 최초 호출될때 생성하는 방식으로써 어플리케이션 로드에 걸리는 부담을 경감시켜주는 효과가 있다.
2. Inversion of Control • 3. Dependency Injection • : 스프링닷넷 프레임웍은 설정 파일 내에서 객체간의 의존 관계를 설정할 수 있다. 이는 디자인패턴의 Factory Method Pattern에서의 팩토리 클래스와 같은 효과를 가진다. • <object id=“service” type=“ServiceLayer.Service, ServiceLayer”> • <property id=“Dao” ref=“dao”/> • </object> • <object id=“dao” type=“DaoLayer.DAO, DaoLayer”> • 위의 설정은 Service 클래스에서 Property 메소드를 사용해서 DAO 클래스의 인스턴스를 획득하고 있다. • //Service.cs • public class Service : IService • { • private IDAO dao; • public IDAO Dao • { • set { dao = value; } • } • public string SayHello(string name) • { • return dao.HelloDAO(name + " " + TestValue); • } • } • //DAO.cs • public class DAO : IDAO • { • public string HelloDAO(string name) • { • return "HELLO " + name + " FROM DAO"; • } • } • 단, Property를 이용하여 DI를 구현할 경우에는 사용하는 클래스의 디폴트 생성자(아규먼트없는 public 생성자)를 가지고 있어야 하며, 부득이하게 private 으로 선언하여야 할 경우에는 다음으로 소개할 <constructor-arg> 엘리먼트를 사용하여야 한다. • <object id=“service” type=“ServiceLayer.Service, ServiceLayer”> • < constructor-arg name=“Dao” ref=“dao”/> • </object>
2. Inversion of Control • //Service.cs • public class Service : IService • { • private DAO dao; • private Service(){} • private Service(DAO dao) • { • this.dao = dao; • } • public string SayHello(string name) • { • return dao.HelloDAO(name + " " + TestValue); • } • } • 그러나, 위와 같이 구현할 경우는 그리 많지 않을것이며, 스프링닷넷 프레임웍의 개발 리드를 맡고 있는 Mark Polarck 또한 Property 를 이용한 DI 사용을 권장하고 있다. • 이처럼, DI 기능을 사용하여 객체를 생성하는 방법에는 Property를 이용하는 방법과 생성자를 이용하는 방법 두가지가 있다. • ASP.NET에서는 웹어플리케이션이 로드될 때 자동적으로 IApplicationContext를 로딩해준다. 따라서 웹페이지에서는 바로 DI 기능을 사용할 수 있다. 하지만 윈폼에서는 아직 IApplicationContext의 로딩을 자동화해주지 않으므로 최초에 한번은 프로그래머가 직접 로딩해 주어야 한다. • // Program.cs • static class Program { • [STAThread] • static void Main() { • try { • Application.EnableVisualStyles(); • Application.SetCompatibleTextRenderingDefault(false); • // ApplicationContext를 로딩 • IApplicationContext ctx = ContextRegistry.GetContext(); • Form mainForm = (Form)ctx["mainForm"]; • Application.Run(mainForm); • } catch(Exception x) {} • } • } • // App.Config • <object id="mainForm" type=“TestNS.frmMain, TestNS"></object>
2. Inversion of Control • 4. 설정파일에서의 ApplicationContext 설정방법 • : 아래는 일반적인 설정파일의 형태이다. configSections 엘리먼트내에서 spring 섹션 그룹을 설정하고 그 내부에 context, objects 섹션을 설정한다. • <?xml version="1.0" encoding="utf-8" ?> • <configuration> • <configSections> • <sectionGroup name="spring"> • <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" /> • <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> • </sectionGroup> • </configSections> • <spring> • <context> • <resource uri="config://spring/objects"/> • </context> • <objects xmlns="http://www.springframework.net"> • <object id="dao" type="MySpringSample_05.DAO, MySpringSample_05" > • </object> • <object id="serviceBase" type="MySpringSample_05.ServiceBase, MySpringSample_05"> • <property name="Dao" ref="dao"/> • </object> • <object id="service" • type="MySpringSample_05.Service, MySpringSample_05" • parent="serviceBase" • singleton="true" • lazy-init="true" > • </object> • </objects> • </spring> • </configuration> • 설정할 내용이 많을 경우 objects 엘리먼트의 내용은 부속 xml 파일로 빼낼 수 있다. 그러기 위해서는 다음과 같이 지정한다. 단, 주의할 점은 부속 xml 파일의 빌드 속성을 “포함 리소스”로 변경하는것을 절대 잊어선 안된다. • <spring> • <context type="Spring.Context.Support.XmlApplicationContext, Spring.Core"> • <resource uri="file://objects.xml"/> • <resource uri="assembly://MyAssembly/MyProject/objects-dal-layer.xml"/> • </context> • </spring>
3. AOP • 1. AOP의 개념 • : Aspected Oriented Programming 을 우리말로 굳이 번역하자면 관점 지향 프로그래밍 정도일것이다.(아마도 더 헷갈릴듯 -.-) 여기서 말하는 관점을 주관심사(Core Concerns)와 횡단관심사(Cross Cutting Concerns)로 나눌 수 있는데, 주관심사는 비즈니스 로직이 될 수 있고, 횡단관심사는 비즈니스 로직에 사용되는 로깅, 트랜잭션, 인증 등과 같은 로직들이다. • 어플리케이션을 개발하는동안 개발자는 주관심사만 개발하는 것이 아니라 어쩔 수 없이 횡단관심사도 개발해야만 한다. AOP에서는 개발자는 주관심사에만 집중하고 횡단관심사들은 컨테이너에 맡겨버려서 개발 속도를 향상시키고 객체지향의 원래 목적에 더욱 더 충실하자는 것이 AOP가 지향하는 목적이라고 볼 수 있다. 로 깅 (메소드 호출, 예외 처리 등) 주관심사 트 랜 잭 션 처 리 회원정보조회 회원 등록 회원 탈퇴 인 증 (접근 제한, 자격 관리) { 횡단 관심사
3. AOP • 2. AOP의 주요 용어 정리 • Joinpoint • AOP에서 Jointpoint는 클래스의 인스턴스 생성 시점, 메쏘드를 호출하는 시점, Exception이 발생하는 시점과 같이 애플리케이션을 실행할 때 특정 작업이 실행되는 시점을 의미한다. • Target • 실질적인 비즈니스 로직 부분. • 주관심사. • Advice • Logging, Exception, Transaction, Email, Message, Security 등과 같이 실질적인 비즈니스 로직(Target, 횡단 관심사)에 추가적인 기능을 제공하는 것을 말한다. • 횡단 관심사. 스프링닷넷 프레임웍에서 제공하는 Advice에는 before, after, around, throws가 있다. • Pointcut • 분리된 기능들(Target과 Advice, 종단 관심사와 횡단 관심사 )을 결합시키기 위한 규칙(패턴) • Aspect • Advice와 Pointcut을 합쳐서 하나의 Aspect라고 한다. 즉, 일정한 패턴을 가지는 클래스에 Advice를 적용하도록 지원할 수 있는 것을 Aspect라고 한다. • 애플리케이션 개발을 위하여 세운 일정한 패턴을 가진 정책. • 예) 로깅은 메쏘드 시작과 끝 지점에 남긴다. • Weaving • Target과 Advice를 결합시키는 것을 의미한다. 분리하여 개발된 기능들을 Weaving하는 작업을 도와주는 것이 AOP 툴이 하는 역할이다. • - 스프링프레임워크 워크북(박재성 저)에서 발췌
3. AOP • 3. before, around, after, throws advice • : 스프링닷넷에서 제공하는 Advice에는 before, around, after, throws 네가지가 있다. 단어에서 유추할 수 있듯이 before는 특정 메소드가 호출되기전에 인터셉트됨을 의미하며, around는 메소드가 실행되기 바로 전과 후에, after는 실행 직후에, throws는 예외가 발생했을때 인터셉트된다. • 1) before Advice 구현 • public class CountingBeforeAdvice : IMethodBeforeAdvice { • public void Before(MethodInfo method, object[] args, object target) { • Console.WriteLine(“메소드 호출전”); • } • } • : before Advice는 IMethodBoforeAdvice 인터페이스를 구현한 클래스의 Before 메소드에서 실행된다.
3. AOP • 2) around Advice 구현 • public class DebugInterceptor : IMethodInterceptor { • public object Invoke(IMethodInvocation invocation) { • Console.WriteLine(“메소드 실행전”); • object rval = invocation.Proceed(); • Console.WriteLine(“메소드 실행직후"); • return rval; • } • } • : around Advice는 IMethodInterceptor 인터페이스를 구현한 클래스의 Invoke 메소드에서 실행된다. 인자로 전달받은 invocation의 Proceed 메소드가 실행될때 타겟 메소드가 실행된다. • 3) after Advice 구현 • public class CountingAfterReturningAdvice : IAfterReturningAdvice { • public void AfterReturning(object returnValue, MethodBase m, object[] args, object target) { • Console.WriteLine(“메소드 실행 직후”); • } • } • : after Advice는 타겟 메소드가 실행된 직후에 IAfterReturningAdvice 인터페이스를 구현한 클래스의 AfterReturning 메소드가 실행된다. • 4) throws Advice 구현 • public class CombinedThrowsAdvice : IThrowsAdvice { • public void AfterThrowing(RemotingException ex) { • // Do something with remoting exception • } • public void AfterThrowing(MethodInfo method, object[] args, object target, SqlException ex) { • // Do something will all arguments • } • } • : throws Advice는 예외가 발생될 때 IThrowsAdvice 인터페이스를 구현한 클래스의 AfterThrowing 메소드가 실행된다. • AfterThrowing 메소드의 인자로 특정 Exception 객체를 선언하면 해당 예외가 발생할 때만 호출된다.
3. AOP • 4. Aspect 설정 방법 • <objects xmlns='http://www.springframework.net'> • <object id="beforeAdvice" • type="MySpringSample_AOP.AspectObject.BeforeLog, MySpringSample_AOP" /> • <object id="afterAdvice" • type="MySpringSample_AOP.AspectObject.AfterLog, MySpringSample_AOP" /> • <object id="aroundAdvice" • type="MySpringSample_AOP.AspectObject.AroundLog, MySpringSample_AOP" /> • <object id="throwsAdvice" • type="MySpringSample_AOP.AspectObject.ExceptionLog, MySpringSample_AOP" /> • <object id="DAOproxy" type="Spring.Aop.Framework.ProxyFactoryObject"> • <property name="Target"> • <object type="MySpringSample_AOP.DAO, MySpringSample_AOP" /> • </property> • <property name="InterceptorNames"> • <list> • <value>beforeAdvice</value> • <value>afterAdvice</value> • <value>aroundAdvice</value> • <value>throwsAdvice</value> • </list> • </property> • </object> • </objects> • : Aspect를 설정하는 방법은 위에서 보듯이 Advice들을 구현한 object를 선언한 후에 타겟 객체를 지정하면 해당 객체의 메소드가 실행될 때 “interceptorNames”Property의 “list”엘리먼트에서 지정한 Advice들이 해당 메소드의 실행을 가로채게 된다. 즉, 위에서는 DAO 객체의 메소드가 실행될 때 Advice가 작동하게 되는것이다.
3. AOP • 5. AutoProxy • : Auto Proxy 기능은 특정 클래스나 특정 메소드들만 Aspect 할 수 있는 기능을 말한다. 이 기능을 사용하면 객체들마다 Aspect를 설정해야하는 번거로움을 제거할 수 있다. • 1) 객체 이름(Object 엘리먼트의 id 값)을 기준으로 Aspect • 특정 클래스명을 가진 객체를 Aspect 하기 위해서는 ObjectNameAutoProxyCreator를 구현한다. 아래의 설정 예제를 보자. • <object id="aroundAdvice" • type="MySpringSample_AOP.AspectObject.AroundLog, MySpringSample_AOP" /> • <object id="ProxyCreator" • type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop"> • <property name="ObjectNames"> • <list> • <value>DAO*</value> • </list> • </property> • <property name="InterceptorNames"> • <list> • <value>aroundAdvice</value> • </list> • </property> • </object> • <object id="DAOproxy" type="MySpringSample_AOP.DAO, MySpringSample_AOP" /> • 위의 예제에서는 “DAO”이름으로 시작하는 id를 가진 모든 객체의 메소드를 Aspect하게된다.
3. AOP • 2) 메소드 이름을 기준으로 Aspect • : 메소드 이름을 기준으로 Auto Proxy를 구현하기 위해서는 NameMatchMethodPointcutAdvisor를 사용해야한다. • <object id="aroundAdvice" • type="MySpringSample_AOP.AspectObject.AroundLog, MySpringSample_AOP" /> • <object id="aroundAdvisor" • type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop"> • <property name="Advice" ref="aroundAdvice"/> • <property name="MappedNames"> • <list> • <value>Save*</value> • </list> • </property> • </object> • <!– DAO 객체에만 지정 --> • <object id="DAOproxy" type="Spring.Aop.Framework.ProxyFactoryObject"> • <property name="Target"> • <object type="MySpringSample_AOP.DAO, MySpringSample_AOP" /> • </property> • <property name="InterceptorNames"> • <list> • <value>aroundAdvisor</value> • </list> • </property> • </object> • <!-- 모든 객체에 지정 --> • <object id="DAOproxy" type="MySpringSample_AOP.DAO, MySpringSample_AOP" /> • <object type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator, Spring.Aop" /> • --> • 위의 예제에서는 DAO 객체의 Save로 시작하는 메소드의 경우에만 Aspect를 실행한다. • 물론, 객체명과, 메소드명을 혼합해서 사용하는 것도 가능하다. • 또, 주석처리 되어있는 DefaultAdvisorAutoProxyCreator를 사용하면 context에 지정된 모든 객체의 Save로 시작하는 메소드를 대상으로 Aspect를 실행할 수도 있다.
4. Data Access • 1. dbProvider • : 스프링닷넷에서 제공하는 데이타베이스 provider는 아래와 같다. • SqlServer-1.1 - Microsoft SQL Server, provider V1.0.5000.0 in framework .NET V1.1 • SqlServer-2.0 (aliased to System.Data.SqlClient) - Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0 • SqlServerCe-3.1 (aliased to System.Data.SqlServerCe) - Microsoft SQL Server Compact Edition, provider V9.0.242.0 • OleDb-1.1 - OleDb, provider V1.0.5000.0 in framework .NET V1.1 • OleDb-2.0 (aliased to System.Data.OleDb) - OleDb, provider V2.0.0.0 in framework .NET V2.0 • OracleClient-2.0 (aliased to System.Data.OracleClient) - Oracle, Microsoft provider V2.0.0.0 • OracleODP-2.0 (aliased to System.DataAccess.Client) - Oracle, Oracle provider V2.102.2.20 • SQLite-1.0.43 - (aliased to System.Data.SQLite) - SQLite provider 1.0.43 for .NET Framework 2.0 • (MySql과 DB2는 매뉴얼을 참조하길 바람) • 설정파일에서는 아래와 같이 지정한다. • <objects xmlns='http://www.springframework.net' • xmlns:db="http://www.springframework.net/database"> • <db:provider id=“dbProvider" • provider=“SqlServer-2.0“ (또는, provider=“System.Data.SqlClient”) • connectionString="Data Source=(local);Database=Spring;User ID=springqa;Password=springqa;Trusted_Connection=False"/> • <object id="adoTemplate" type="Spring.Data.AdoTemplate, Spring.Data"> • <property name="DbProvider" ref=“dbProvider"/> • </object> • </objects>
4. Data Access • 2. AdoTemplate • : 스프링닷넷은 데이타베이스 액세스를 위한 간편한 랩퍼클래스를 제공하며, 그것이 AdoTemplate이다. AdoTemplate은 CRUD를 위한 다양한 메소드를 제공하고 있다. • 입력성 쿼리를 위한 ExecuteNonQuery, 단일값 반환을 위한 ExecuteScalar, 로우값을 사용자 지정 객체로 반환해주는 QueryWithResultSetExtractor, QueryWithRowMapper, QueryForObject 데이타셋이나 데이타테이블로 결과값을 반환해 주는 DataTableCreate, DataSetCreate 등 다양한 메소드를 지원해 준다. • <objects xmlns="http://www.springframework.net" • xmlns:db="http://www.springframework.net/database"> • <db:provider id="dbProvider" • provider="SqlServer-2.0" • connectionString="Data Source=khjnote;Initial Catalog=TEST_DB;Persist Security Info=True;User ID=sa;Password=showmethepower"/> • <object id="adoTemplate" type="Spring.Data.Core.AdoTemplate, Spring.Data"> • <property name="DbProvider" ref="dbProvider"/> • </object> • <object id="dao" type="MySpringSample_06.DAO, MySpringSample_06"> • <property name="AdoTemplate" ref="adoTemplate"/> • </object> • </objects> • public class DAO : AdoDaoSupport, IDAO { • public void Insert(string logonid, string name) { • string query = "insert into users(logonid, name) values(@logonid, @name)"; • IDbParametersBuilder builder = CreateDbParametersBuilder(); • builder.Create().Name("logonid").Value(logonid); • builder.Create().Name("name").Value(name); • AdoTemplate.ExecuteNonQuery(CommandType.Text, query, builder.GetParameters()); • } • } • 위 예제는 AdoTemplate을 통해서 데이터를 입력하고 있으며, 설정파일에서 DbProvider를 DAO 클래스의 AdoTemplate에 지정하였다.
4. Data Access • : 아래의 예제는 여러줄의 데이터를 IList 타입의 사용자 지정 객체로 반환받고 있다. • // DAO.cs • public class DAO : AdoDaoSupport, IDAO { • public IList SelectAll() { • string query = "select logonid, name from users"; • return AdoTemplate.QueryWithRowMapper(CommandType.Text, query, new UserMapper()); • } • } • // UserMapper.cs • public class UserMapper : IRowMapper { • public object MapRow(System.Data.IDataReader reader, int rowNum) { • UserEntity userEntity = new UserEntity(); • userEntity.Logonid = reader.GetString(0); • userEntity.Name = reader.GetString(1); • return userEntity; • } • } • // UserEntity.cs • [Serializable] • public class UserEntity • { • private string logonid; • private string name; • public string Logonid • { • get { return logonid; } • set { logonid = value; } • } • public string Name • { • get { return name; } • set { name = value; } • } • } • UserMapper 객체를 통해 데이타리더로 받은 결과로우를 UserEntity 객체 콜렉션으로 반환하고 있다.
4. Data Access • 3. 네임스페이스 파서 • : 설정파일에서 주의할점으로 네임스페이스 파서를 반드시 등록하는 것이다. • 그렇지 않으면 설정파일의 스키마를 해석하지 못하는 오류가 발생한다. • <?xml version="1.0" encoding="utf-8" ?> • <configuration> • <configSections> • <sectionGroup name="spring"> • <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" /> • <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> • <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" /> • </sectionGroup> • </configSections> • <spring> • <parsers> • <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> • <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /> • </parsers> • <context> • <resource uri="assembly://MySpringSample_06/MySpringSample_06/Service.xml"/> • <resource uri="assembly://MySpringSample_06/MySpringSample_06/DAO.xml"/> • </context> • </spring> • </configuration> • DatabaseNamespaceParser는 xmlns:db="http://www.springframework.net/database“ 스키마를 파싱하도록 도와주며, TxNamespaceParser는 xmlns:tx="http://www.springframework.net/tx“ 스키마를 파싱하도록 도와주는 역할을 실행한다.
4. Data Access • 4. 트랜잭션 전략 • : 스프링닷넷에서 트랜잭션을 제어하기 위해서는 해당 메소드에 [Transaction] 어트리뷰트를 선언하고 설정파일에서는 아래의 코드를 삽입한다. • <object id="transactionManager" • type="Spring.Data.Core.TxScopeTransactionManager, Spring.Data"> • </object> • <tx:attribute-driven transaction-manager="transactionManager"/> • 또한 트랜잭션 네임스페이스 파서를 등록하는 것을 잊지 않도록 한다. • <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /> • [Transaction] • public void CreateUser(string logonid, string name) • { • Dao.Insert(logonid, name); • throw new Exception("강제 예외 실행"); • Dao.Insert(logonid, name); • } • 아래는 특정 메소드에만 트랜잭션을 설정하는 방법이다. Create로 시작하는 메소드는 모두 트랜잭션 기능이 적용된다. • <tx:advice id="txAdvice" transaction-manager="transactionManager"> • <tx:attributes > • <tx:method name="Create*"/> • </tx:attributes> • </tx:advice> • 트랜잭션에 관해서는 다양한 옵션이 존재하므로 매뉴얼을 참조하길 바람. • 주의 : 스프링닷넷의 트랜잭션을 사용하기 위해서는 반드시 인터페이스를 구현해야함.
5. WebService • 1. Server Side • : 스프링닷넷에서는 PONO를 설정만으로 손쉽게 웹서비스, 엔터프라이즈 서비스, 닷넷리모팅으로 포팅해준다. 스프링닷넷팀이 웹서비스를 지원하게된 이유는 1.별다른 사용용도가 없는 *.asmx 파일을 제거하고, 2.웹서비스에서도 DI 기능을 지원하고, 3.PONO를 그대로 웹서비스로 포팅하며, 4.클라이언트 영역에서 웹서비스를 일반 라이브러리에 접근하듯이 손쉽게 사용하기 위해서이다. • 스프링닷넷의 웹서비스 기능을 사용하기 위해서는 PONO 객체와 이를 호스팅해줄 웹사이트를 준비해야한다. • namespace HelloWorldApp • { • public interface IHelloWorld { • string HelloWorld(); • } • public class HelloWorldService:IHelloWorld • { • private string message; • public string Message { • set { message = value; } • } • public string HelloWorld() { • return this.message; • } • public string SayNo() { • return "No"; • } • } • } PONO - WebServiceExporter - WebServiceHandlerFactory - WebSupportModule ① 컴파일, 프락시확인 WS consumer IIS (Webservice Hosting) ② Request 전송 스프링닷넷의 웹서비스를 사용하기위해 PONO 측에서 해야할 단 한가지의 작업이 있는데 그것은 인터페이스를 구현해야한다는 점이다. 그리고 인터페이스에서 선언한 메소드들만이 WebServiceExporter에 의해 웹메소드로 사용될 수 있다.
5. WebService • : 다음은 PONO를 웹서비스로 포팅할 웹사이트의 Web.Config 이다. (일부발췌.) • <objects xmlns="http://www.springframework.net"> • <object id="helloWorld" type="HelloWorldApp.HelloWorldService, HelloWorldApp"> • <property name="Message" value=“안녕하세요!"/> • </object> • <object id="HelloWorldService" type="Spring.Web.Services.WebServiceExporter, Spring.Web"> • <property name="TargetName" value="helloWorld"/> • <property name="Namespace" value="http://MySpringSample_WS/HelloWorldService"/> • </object> • </objects> • <system.web> • <httpHandlers> • <add verb="*" path="*.asmx" • type="Spring.Web.Services.WebServiceHandlerFactory, Spring.Web"/> • </httpHandlers> • <httpModules> • <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/> • </httpModules> • </system.web> • 설정이 완료되었으면 디폴트페이지에 링크를 걸어 HelloWorldService.asmx를 확인한다. • <body> • <table width="100%" height="100%" align="center" valign="middle"> • <tr> • <td align="center"> • <h2><a href="HelloWorldService.asmx">helloWorldService</a></h2> • </td> • </tr> • </table> • </body> http://웹사이트이름 /HelloWorldService.asmx 로 서비스됨.
5. WebService • 2. Client Side • : 클라이언트에서는 PONO 모듈을 참조한 후에 설정 파일에서 해당 웹서비스를 사용하겠다는 선언을 하면된다. • <object id="helloWorldService" • type="Spring.Web.Services.WebServiceProxyFactory, Spring.Services"> • <property name="ServiceUri" value="http://localhost/HelloWorldWeb/helloworldservice.asmx"/> • <property name="ServiceInterface" value="HelloWorldApp.IHelloWorld, HelloWorldApp"/> • <property name="ProductTemplate"> • <object> • <property name="Timeout" value="10000" /> 웹메소드를 호출후 기다리는 시간 10초 설정 • </object> • </property> • </object> • 설정 파일에서는 위의 설정만으로 충분하며 클라이언트 코드에서는 일반적인 DI 기능을 사용하듯이 사용하면 된다. • private IHelloWorld serviceHello; • public IHelloWorld ServiceHello • { • get { return serviceHello; } • set { serviceHello = value; } • } • private void button1_Click(object sender, EventArgs e) • { • string s = ServiceHello.HelloWorld(); • MessageBox.Show(s); • }
6. Sample • 샘플 #1. • - MySpringSample_01 • : 기본적인 IoC 기능 구현 • 샘플 #2. • - MySpringSample_02, MySpringSample_03 • : 기본 설정 파일이 아닌 외부에서 XML 파일로 IoC 기능을 설정하는 방법 • : Application Context를 헬퍼파일로부터 생성하는 방법 • 샘플 #3. • - MySpringSample_04 • : 간단한 AOP 기능 구현 • 샘플 #4. • - MySpringSample_05 • : 객체 생성시 다양한 옵션 활용법 • : IoC를 이용한 상속 기능 활용 • 샘플 #5. • - MySpringSample_06 • : 트랜잭션 설정 방법 • 샘플 #6. • - MySpringSample_07 • : Winform에서 우회적으로 DI를 사용하는 방법 • 샘플 #7. • : 웹서비스 기능 샘플 • - HelloWorldApp • : PONO 비즈니스 모듈 • - HelloWorldWeb • : HelloWorldApp를 웹서비스로 호스팅해줄 웹사이트 • - MySpringSample_WS_Client • : 웹서비스를 사용하는 클라이언트
부 서 : ㈜중외정보기술 개발본부 연구팀 • 성 명 : 권효중 • 메 일 : khj@cwit.co.kr, fog_rain@naver.com • 전 화 : 016-676-1072 • 주 소 : 서울시 구로구 구로3동 이앤씨벤처드림타워6차 1002호 감사합니다.