• 데코레이터 패턴
    • 객체를 감싸서 새로운 행동을 제공
  • 스테이트 패턴
    • 상태를 기반으로 한 행동을 캡슐화한 다음 위임을 통해서 필요한 행동을 선택
  • 이터레이터 패턴
    • 켈렉션이 어떤식으로 구현되었는지 드러내진 않으면서도 컬렉션 내에 있는 모든 객체에 대해 반복 작업을 처리할 수 있게 해준다.
  • 퍼사트 패턴
    • 일련의 클래스에 대해서 간단한 인터페이스를 제공한다.
  • 스트레티지 패턴
    • 교환 가능한 행동을 캡슐화 하고 위임을 통해서 어떤 행동을 사용할 지 결정한다.
  • 프록시 패턴
    • 객체를 감싸서 그 객체에 대한 접근을 제어한다.
  • 팩토리 메소드 패턴
    • 생성할 구상클래스를 서브클래스에서 결정한다.
  • 어댑터 패턴
    • 객체를 감싸서 다른 인터페이스를 제공한다.
  • 옵저버 패턴
    • 상태가 변경되면 다른 객체들 한테 연락을 돌릴 수 있게 해줍니다.
  • 템플릿 메소드 패턴
    • 알고리즘의 개별단계에서 구현하는 방법을 서브클래스에서 결정한다.
  • 컴포지트 패턴
    • 클라이언트에서 객체 컬렉션과 개별 객체를 똑같이 다룰 수 있도록 해준다.
  • 싱글톤 패턴
    • 딱 한 객체만 생성되게 한다.
  • 추상팩토리 패턴
    • 클라이언트에서 구상클래스를 지정하지 않으면서도 일군의 객체를 생성할 수 있도록 해준다.
  • 커맨드 패턴
    • 요청을 객체로 감싼다.

저작자 표시
Posted by lonekim 영근

잘 동작하던 녀석이 주말을 지내고 나선 작동이 안된다.


오류 내용은 

심각: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderList

ener

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 31 in XML document from ServletContext resource [/WEB

-INF/spring/root-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 75; cv

c-complex-type.2.4.c: 일치하는 와일드 카드 문자가 엄격하게 적용되지만 'util:properties' 요소에 대한 선언을 찾을 수 없습니다.

    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)


원인을 찾아보니 pom.xml에 정의한 스프링 버전보다 높은 스키마 버전을 빈설정파일에서 사용하고 있었다.


<org.springframework-version>3.1.0.RELEASE</org.springframework-version>

pom.xml


스프링 버전을 맞춰줘서 해결.

Posted by lonekim 영근
iBatis 관련글 링크

http://opensource.atlassian.com/confluence/oss/display/IBATIS/Environment+Specific+Information


Posted by lonekim 영근
import junit.framework.TestCase;

public class StringTest extends TestCase {
    public void testSplit()  {                
        String str = "안녕하세요|반갑습니다";
        String[] resultA = str.split("|");
        for (String string : resultA) {
            System.out.println(string);
        }
        
        String[] resultB = str.split("[|]");
        for (String string : resultB) {
            System.out.println(string);
        }        
    }
}



result :





|





안녕하세요
반갑습니다

|을 정규표현식으로 인식되기 때문에
[]로 감싸줘야 원하는 결과를 얻을 수 있음.

아래 링크를 보시면
StringTokenizer 와 split에 대해 자세히 알수 있습니다.
링크
Posted by lonekim 영근
TAG Split
새 텍스트 문서.txt 와 같이 공백이 있는 파일명을 가진 파일을 다운로드 할때
+(새+텍스트+문서.txt)가 붙는 경우에

java.net.URLEncoder.encode(filename, "UTF-8").replace("+", "%20")
Posted by lonekim 영근
상황:
본문을 CLOB type로 넣기
본문이 UTF-8 HTML형태로 되어 있음
HTML을 읽어서 String으로 저장하기.

처음 삽질:
 
   private static StringBuilder htmlReader(String filename) {
        FileReader fr;      
        String htmlFileName = filename;
        StringBuilder builder = null;
        try {
            fr = new FileReader (htmlFileName);                
            BufferedReader in = new BufferedReader( fr );
            builder = new StringBuilder();
            String  s = null;   
            while ((s = in.readLine()) != null) {
                builder.append(s);
            }           
            in.close();               
        } catch (FileNotFoundException e) {           
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return builder;
    }

..데이터가 깨진다.

해결:
FileReader 대신 FileInputStream을 이용.
    private static StringBuilder htmlReader(String filename) {
        BufferedReader bufferedReader;
        InputStreamReader inputStreamReader;
        FileInputStream fileInputStream;
        StringBuilder builder = null;              
        String htmlFileName = filename;
        try {
            fileInputStream = new FileInputStream(htmlFileName);            
            inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
            bufferedReader = new BufferedReader(inputStreamReader);
            builder = new StringBuilder();
            String  temp = null;    
            while ((temp = bufferedReader.readLine()) != null) {
                builder.append(temp);
            }            
            bufferedReader.close();                
        } catch (FileNotFoundException e) {            
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return builder;
    }


java io 제대로 알아야 겠다.
Posted by lonekim 영근
자바스크립트를 이용해서 피보나치수열을  TDD를 이용해서 구현하네요.
자바스크립트로 TDD를  시연한 동영상

jsunit 홈페이지 : 이클립스 플러그인도 함께 제공합니다.
Posted by lonekim 영근
TAG jsunit, TDD
Test-Driven Development by Example(TDDBE) 를 읽고나서, 예전에 가지고 있었던 TDD에 대한 생각이 많이 바뀌었다. 예전까지 TDD는 코드를 테스트하기 위한 방법으로 생각하고 있었는데, 책 뒷부분에 TDD를 단순히 테스트라고 생각하지 말고, TDD를 하나의 개발방법으로 이해하라라고 나오는데, 책을 읽어가다 보면 쉽게 공감할 수가 있다.

내가 처음 TDD를 접한 것은 Agile Java책을 공부하면서 였는데, 실제 클래스를 작성하지 않고, 먼저 테스트 클래스를 만들었던것 같다. 그 때 책의 예제를 Eclipse를 통해서 따라했는데, 테스트클래스를 먼저 만들게 되면, eclipse에 온통 빨간줄 투성이었다. 그래서 예제를 빨리 따라해보고 싶어서 먼저 실제 클래스를 작성하고, 거기에서 테스트 클래스를 만들었다.

하지만 TDDBE를 읽고나서 그 방식이 잘못되었다는 것을 바로 알게 되었다. 켄트 벡이 설명하는 TDD방식은 작은 테스트를 추가하고, 테스트를 실패하는 것을 확인하고, 테스트가 성공하도록 하고, 중복을 제거하기 위해 리팩토링을 사용한다.

책에서 Money라는 예제를 통해 실질적으로 TDD하는 방법을 보여주고 있으며, 그 방법을 따라가면서 TDD를 충분히 맛볼수 있다.

TDD를 하기위해선 기본적으로 디자인패턴과 리팩토링에 대한 선수지식이 필요한 것같다.
TDD에선 디자인 패턴과 리팩토링이 많이 접목되어 있습니다. TDD와 함께 디자인패턴, 리팩토링을 함께 공부하면 더 좋은 결과를 얻을 수 있을 것 같습니다.

책에서 간략히 다루긴 하지만 디자인 패턴과 리팩토링이 익숙하다면 TDD에 적응하기가 더욱 빠를 수 있을 것이다. 또한 TDD를 익히기 위해선 변화를 포용할 수 있는 마인드를 가지는것이 중요할 것이다.
Posted by lonekim 영근
하나 이상의 Pointcut을 이용하길 원할때 ComposablePointcut을 사용한다.

package com.youngkun.aoptest.pointcut;

public class SampleBean2 {
   public String getName(){
       return "김영근";
   }
   public void setName(String name){
      
   }
   public int getAge(){
       return 100;
   }
}


package com.youngkun.aoptest.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.Advisor;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcher;

public class ComposablePointcutExample {

   public static void main(String[] args) {
       SampleBean2 target = new SampleBean2();
       ComposablePointcut pc =
           new ComposablePointcut(ClassFilter.TRUE, new GetterMethodMatcher());
      
       System.out.println("Test 1");
       SampleBean2 proxy = getProxy(pc, target);
       testInvoke(proxy);
      
       System.out.println("Test 2");
       //get으로 시작하는 메소드와 set으로 시작하는 메소드를 확인
       //union은 이전의 pointcut과 현재 pointcut을 모두 적용
       pc.union(new SetterMethodMatcher());
       proxy = getProxy(pc, target);
       testInvoke(proxy);
      
       System.out.println("Test 3");
       //이름이 getAge인 메소드만 확인
       //현재 pointcut만 적용되도록 확인
       pc.intersection(new GetAgeMethodMatcher());
       proxy = getProxy(pc, target);
       testInvoke(proxy);
   }
  
   private static SampleBean2 getProxy(ComposablePointcut pc, SampleBean2 target){
       Advisor advisor = new DefaultPointcutAdvisor(pc, new SimpleBeforeAdvice());
       ProxyFactory pf = new ProxyFactory();
       pf.setTarget(target);
       pf.addAdvisor(advisor);
       return (SampleBean2)pf.getProxy();
   }
  
   private static void testInvoke(SampleBean2 proxy){
       proxy.getAge();
       proxy.getName();
       proxy.setName("김영근");
   }
  
   //get으로 시작하는 메소드를 확인
   private static class GetterMethodMatcher extends StaticMethodMatcher{
       public boolean matches(Method method, Class cls){
           return (method.getName().startsWith("get"));
       }
   }
  
   //메소드의 이름이 getAge인 것을 확인
   private static class GetAgeMethodMatcher extends StaticMethodMatcher{
       public boolean matches(Method method, Class cls){
           return "getAge".equals(method.getName());
       }
   }
  
   //set으로 시작하는 메소드를 확인
   private static class SetterMethodMatcher extends StaticMethodMatcher{
       public boolean matches(Method method, Class cls){
           return (method.getName().startsWith("set"));
       }
   }

}


결과
Test1에서는 get으로 시작하는 메소드가 advised
Test2에서는 get으로 시작하는 메소드와 set으로 시작하는 메소드가 advised(union)
Test3에서는 이름이 getAge인 메소드만 호출(intersection)
Test 1
Before method : public int com.youngkun.aoptest.pointcut.SampleBean2.getAge()
Before method : public java.lang.String com.youngkun.aoptest.pointcut.SampleBean2.getName()
Test 2
Before method : public int com.youngkun.aoptest.pointcut.SampleBean2.getAge()
Before method : public java.lang.String com.youngkun.aoptest.pointcut.SampleBean2.getName()
Before method : public void com.youngkun.aoptest.pointcut.SampleBean2.setName(java.lang.String)
Test 3
Before method : public int com.youngkun.aoptest.pointcut.SampleBean2.getAge()

Posted by lonekim 영근
advise할 메소드가 다른(another), 특정한(specific)한 메소드에 의해 호출될때 advised되기를 원할때 사용된다.

package com.youngkun.aoptest.pointcut;

public class TestBean {
   public void foo(){
       System.out.println("foo()");
   }
}


package com.youngkun.aoptest.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class SimpleBeforeAdvice implements MethodBeforeAdvice {

   public void before(Method method, Object[] args, Object target)
           throws Throwable {
       System.out.println("Before method : " + method);
   }

}


package com.youngkun.aoptest.pointcut;

import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.ControlFlowPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class ControlFlowExample {
   public static void main(String[] args) {
       ControlFlowExample ex = new ControlFlowExample();
       ex.run();
   }

   private void run() {
       TestBean target = new TestBean();
      
       //create advisor
       Pointcut pc = new ControlFlowPointcut(ControlFlowExample.class, "test");
       Advisor advisor = new DefaultPointcutAdvisor(pc, new SimpleBeforeAdvice());
      
       //create proxy
       ProxyFactory pf = new ProxyFactory();
       pf.setTarget(target);
       pf.addAdvisor(advisor);
      
       TestBean proxy = (TestBean)pf.getProxy();
      
       System.out.println("Trying normal invoke");
       proxy.foo();
       System.out.println("Trying under ControlFlowExample.test()");
       test(proxy);
   }
  
   private void test(TestBean bean){
       bean.foo();
   }

}


실행결과
test()라는 다른 메소드에서 foo()가 호출될때 advised가 되는 것을 확인 할 수 있다.
Trying normal invoke
foo()
Trying under ControlFlowExample.test()
Before method : public void com.youngkun.aoptest.pointcut.TestBean.foo()
foo()

하지만 1.4JVM에서는 5배, 1.3JVM에서는 10배정도 느려진다는거~
Posted by lonekim 영근
만약 모든 메소드의 이름을 알지 못하고 이름의 패턴을 알때 정규표현식을 이용한 JdkRegexpMethodPointcut 또는 Perl5RegexpMethodPointcut사용할 수 있다.

package com.youngkun.aoptest.pointcut;

public class RegexpBean {
   public void foo1() {
       System.out.println("foo1");
   }
  
   public void foo2() {
       System.out.println("foo2");
   }
  
   public void bar() {
       System.out.println("bar");
   }
}


package com.youngkun.aoptest.pointcut;

import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;

public class RegexpPointcutExample {

   public static void main(String[] args) {
       RegexpBean target = new RegexpBean();
      
       JdkRegexpMethodPointcut pc = new JdkRegexpMethodPointcut();
       pc.setPattern(".*foo.*");
       Advisor advisor = new DefaultPointcutAdvisor(pc, new SimpleAdvice());
      
       ProxyFactory pf = new ProxyFactory();
       pf.setTarget(target);
       pf.addAdvisor(advisor);
       RegexpBean proxy = (RegexpBean)pf.getProxy();
      
       proxy.foo1();
       proxy.foo2();
       proxy.bar();
   }
}


실행결과
  : advised
  : unadvised
>> Invoking foo1
foo1
>> Done
>> Invoking foo2
foo2
>> Done
bar


Pointcut에 사용되는 일반적인 정규표현식 기호
.      임의의 문자 하나와 일치
+      앞의 문자가 하나 이상 발생할 경우 일치함
*      앞의 문자가 없거나 하나 이상일 경우 일치함
\      기호자체를 그대로 사용

Posted by lonekim 영근
메소드 signature나 리턴타입에 상관없이 메소드 이름만으로 매칭하고 싶을 때 StaticMethodMatcherPointcut의 서브클래스를 만들 필요없이  NameMatchMethodPointcut을  사용할 수 있다.


package com.youngkun.aoptest.pointcut;

public class NameBean {
   public void foo() {
       System.out.println("foo");
   }
  
   public void foo(int x) {
       System.out.println("foo " + x);
   }
  
   public void bar() {
       System.out.println("bar");
   }
  
   public void yup() {
       System.out.println("yup");
   }
}



package com.youngkun.aoptest.pointcut;

import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;

public class NamePointcutExample {

   public static void main(String[] args) {
       NameBean target = new NameBean();
      
       //advisor 생성
      
1
NameMatchMethodPointcut pc = new NameMatchMethodPointcut();
       pc.addMethodName("foo");
       pc.addMethodName("bar");
       Advisor advisor = new DefaultPointcutAdvisor(pc, new SimpleAdvice()); 
     
2
NameMatchMethodPointcutAdvisor advisor = new
           NameMatchMethodPointcutAdvisor(new SimpleAdvice());
       advisor.addMethodName("foo");
       advisor.addMethodName("bar");

      
       //proxy 생성
       ProxyFactory pf = new ProxyFactory();
       pf.setTarget(target);
       pf.addAdvisor(advisor);
       NameBean proxy = (NameBean)pf.getProxy();
      
       proxy.foo();
       proxy.foo(999);
       proxy.bar();
       proxy.yup();
   }
}
advisor를 생성할 때 1번을 사용하던 2번을 사용하던 결과는 같다.
2번이 조금더 나아보이네요;

실행결과
붉은색 : advised
파란색 : unadvised
>> Invoking foo
foo
>> Done
>> Invoking foo
foo 999
>> Done
>> Invoking bar
bar
>> Done
yup

Posted by lonekim 영근
package com.youngkun.aoptest.pointcut;

public class SampleBean {
   public void foo(int x){
       System.out.println("Invoked foo() with: " +x);
   }
   public void bar(){
       System.out.println("Invoked bar()");
   }
}


package com.youngkun.aoptest.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.DynamicMethodMatcherPointcut;

public class SimpleDynamicPointcut extends DynamicMethodMatcherPointcut {

   public boolean matches(Method method, Class cls){
       System.out.println("Static check for " + method.getName());
       return ("foo".equals(method.getName()));
   }
  
   public boolean matches(Method method, Class cls, Object[] args) {
       System.out.println("Dynamic check for " + method.getName());
       int x = ((Integer)args[0]).intValue();
       return (x !=100);
   }
   //메소드 매칭메소드에서 클래스를 체크할 필요가 없도록 해준다. 
   public ClassFilter getClassFilter(){
       return new ClassFilter(){
           public boolean matches(Class cls){
               return (cls == SampleBean.class);
           }
       };
   }

}

static 체크와 dynamic체크를 함께사용하는 이유는
bar()메소드가 advised되지 않는 것을 알고 있기 때문에
static체크를 사용함으로써 스프링은 이메소드에 대해 절대 dynamic 체크를 하지 않는다.
만약 static 체크를 사용하지 않는 다면 스프링은 bar()메소드에 대해 일일이 dynamic 체크를 하게 된다.

package com.youngkun.aoptest.pointcut;

import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class DynamicPointcutExample {

   public static void main(String[] args) {
       SampleBean target = new SampleBean();
      
       //advisor 생성
       Advisor  advisor = new DefaultPointcutAdvisor(
               new SimpleDynamicPointcut(), new SimpleAdvice());
      
       //proxy 생성
       ProxyFactory pf = new ProxyFactory();
       pf.setTarget(target);
       pf.addAdvisor(advisor);
       SampleBean proxy = (SampleBean)pf.getProxy();
      
       proxy.foo(1);
       proxy.foo(10);
       proxy.foo(100);
      
       proxy.bar();
       proxy.bar();
       proxy.bar();               
   }
}


실행 결과
붉은색 : static 체크를 통과하고 dynamic 체크를 통과하여 advised된 것
파란색 : static 체크를 통과하고 dynamic 체크를 통과하지 못한것
초록색 : static 체크를 통과하지 못한것.
Static check for foo
Static check for bar
Static check for hashCode
Static check for toString
Static check for foo
Dynamic check for foo
>> Invoking foo
Invoked foo() with: 1
>> Done
Dynamic check for foo
>> Invoking foo
Invoked foo() with: 10
>> Done
Dynamic check for foo
Invoked foo() with: 100
Static check for bar
Invoked bar()
Invoked bar()
Invoked bar()

Posted by lonekim 영근
package com.youngkun.aoptest.pointcut;

public class BeanOne {
   public void foo(){
       System.out.println("foo");
   }
   public void bar(){
       System.out.println("bar");
   }
}


package com.youngkun.aoptest.pointcut;

public class BeanTwo {

   public void foo(){
       System.out.println("foo");
   }
   public void bar(){
       System.out.println("bar");
   }

}


package com.youngkun.aoptest.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.StaticMethodMatcherPointcut;

public class SimpleStaticPointcut extends StaticMethodMatcherPointcut {

   //foo()메소드와 일치
   public boolean matches(Method method, Class cls) {
       return ("foo".equals(method.getName()));
   }
  
   //BeanOne 클래스와 일치
   public ClassFilter getClassFilter(){
       return new ClassFilter(){
           public boolean matches(Class cls){
               return(cls == BeanOne.class);
           }
       };
   }
}


package com.youngkun.aoptest.pointcut;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class SimpleAdvice implements MethodInterceptor {

   public Object invoke(MethodInvocation invocation) throws Throwable {
       System.out.println(">> Invoking " + invocation.getMethod().getName());
       Object retVal = invocation.proceed();
       System.out.println(">> Done");
       return retVal;
   }
}

package com.youngkun.aoptest.pointcut;

import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class StaticPointcutExample {

   public static void main(String[] args) {
       BeanOne one = new BeanOne();
       BeanTwo two = new BeanTwo();
      
       BeanOne proxyOne;
       BeanTwo proxyTwo;
      
       //pointcut, advice, advisor 생성
       Pointcut pc = new SimpleStaticPointcut();
       Advice advice = new SimpleAdvice();
       Advisor advisor = new DefaultPointcutAdvisor(pc, advice);
      
       //BeanOne proxy 생성
       ProxyFactory pf = new ProxyFactory();
       pf.addAdvisor(advisor);
       pf.setTarget(one);
       proxyOne = (BeanOne)pf.getProxy();
      
       //BeanTwo proxy 생성
       pf = new ProxyFactory();
       pf.addAdvisor(advisor);
       pf.setTarget(two);
       proxyTwo = (BeanTwo)pf.getProxy();
      
       proxyOne.foo();
       proxyTwo.foo();
      
       proxyOne.bar();
       proxyTwo.bar();
   }

}


실행결과
붉은색 클래스와 메소드가 일치해서 advice 적용
파란색 클래스와 메소드가 일치하지 않아서 advice가 적용이 안됨
>> Invoking foo
foo
>> Done
foo
bar
bar

Posted by lonekim 영근
Advice가 애플리케이션의 어느부분에 적용할 것인지를 정의한다.
메소드와 클래스에 기초하여 advice를 어디에 weaving할지를 결정한다.

public interface Pointcut{
   ClassFilter getClassFilter();
   MethodMatcher getMethodMatcher();
}

public interface ClassFilter{
   boolean matches(Class clazz);
}

public interface MethodMatcher{
   boolean matches(Method m, Class targetClass);
   boolean isRuntime();
  boolean matches(Method m, Class targetClass, Object[] args);
}

스프링은 isRuntime()을 호출해서 false이면 static이고, true이면 dinamic이다.
static pointcut은 타겟에 대한 모든 메소드에 대해 한번 matches(Method, Class)를 호출한다.
dynamic pointcut은 추가로 matches(Method, Class, Object)를 호출한다.
static pointcut은 호출마다 추가적인 체크를 하지 않기 때문에 성능이 좋다. dynamic pointcut은 복잡한 고레벨에서 사용한다.

public interface PointcutAdvisor{
   pointcut getPointcut();
   Advice getAdvice();
}

Advisor는 Advice와 Pointcut을 합친 것이다.
Pointcut을 구현하기 전에 먼저 Advisor 혹은 PointCutAdvisor을 만들어야 한다.
대부분의 Aspect는 aspect의 행동을 정의한 advice와 aspect가 실행되야 할 위치를 정의한 교차점의 조합으로 이루어진다.



Posted by lonekim 영근

Types of AOP

Programming/java 2007/01/18 10:57
AOP는 weaving process가 발생하는 시점에 이 process가 어떻게 만들어지는지에 따라 구분된다.

Static AOP

처음 AOP구현의 다수가 Static이었다. weaving process는 application 빌드할때 다른 스텝을 형성한다. 자바에서 어플리케이션의 실제 bytecode를 수정하거나 필요에 따라서 코드를 변경하거나 확장하면서 weaving process를 수행한다. 또 advice가 시점을 결정할때 런타임시에 어떠한 일도 할수 없다.
Static AOP의 단점은 단순한 다른 joinpoint를 추가하려고 할때 전체 application을 recompile해주어야 한다. AspecJ가 좋은 예이다.


Dynamic AOP

Dynamic AOP는 weaving process가 런타임 시점에 동적으로 이루어 진다. 이것이 어떻게 구성되는지는 구현하는데에 따른다. 스프링은 모든 advised된 오브젝트에 대해 proxy를 만든다. dynamic AOP의 장점은 메인 애플리케이션코드를 recompile할 필요없이 전체 aspect set을 쉽게 수정할수 있다.


참조 : ProSpring - Introducing Spring AOP

'Programming > java' 카테고리의 다른 글

StaticMethodMatcherPointcut을 사용한 Static Pointcut 예제  (0) 2007/01/18
Pointcut and Advisor  (0) 2007/01/18
Types of AOP  (0) 2007/01/18
AOP 예제4 - Throws Advice  (0) 2007/01/15
AOP 예제3 - After Returning Advice  (0) 2007/01/15
AOP 예제2 - Before Advice  (0) 2007/01/15
Posted by lonekim 영근
package com.youngkun.aoptest;

public class ErrorBean {
   public void errorProneMethod() throws Exception{
       throw new Exception("Foo");
   }
  
   public void otherErrorProneMethod() throws IllegalArgumentException{
       throw new IllegalArgumentException("Bar");
   }
}

package com.youngkun.aoptest;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class SimpleThrowsAdvice implements ThrowsAdvice{
  
   public static void main(String[] args) {
       ErrorBean errorBean = new ErrorBean();
      
       ProxyFactory pf = new ProxyFactory();
       pf.setTarget(errorBean);
       pf.addAdvice(new SimpleThrowsAdvice());
      
       ErrorBean proxy = (ErrorBean)pf.getProxy();
      
       try{
           proxy.errorProneMethod();
       }catch(Exception ignored){}
      
       try{
           proxy.otherErrorProneMethod();
       }catch(Exception ignored){}
   }
  
   public void afterThrowing(Exception ex) throws Throwable{
       System.out.println("***");
       System.out.println("Generic Exception Capture");
       System.out.println("Caught: " + ex.getClass().getName());
       System.out.println("***\n");
   }
  
   public void afterThrowing(Method method, Object[] args, Object target, IllegalArgumentException ex)
       throws Throwable{
       System.out.println("***");
       System.out.println("IllegalArgumentException Capture");
       System.out.println("Caught: "+ ex.getClass().getName());
       System.out.println("Method: "+ method.getName());
       System.out.println("***\n");
   }
}


실행 결과

***
Generic Exception Capture
Caught: java.lang.Exception
***

***
IllegalArgumentException Capture
Caught: java.lang.IllegalArgumentException
Method: otherErrorProneMethod
***

'Programming > java' 카테고리의 다른 글

Pointcut and Advisor  (0) 2007/01/18
Types of AOP  (0) 2007/01/18
AOP 예제4 - Throws Advice  (0) 2007/01/15
AOP 예제3 - After Returning Advice  (0) 2007/01/15
AOP 예제2 - Before Advice  (0) 2007/01/15
AOP 예제1 - around advice  (0) 2007/01/15
Posted by lonekim 영근
package com.youngkun.aoptest;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class SimpleAfterReturningAdvice implements AfterReturningAdvice{
   public static void main(String[] args) {
       MessageWriter target = new MessageWriter();
      
       ProxyFactory pf = new ProxyFactory();
      
       pf.addAdvice(new SimpleAfterReturningAdvice());
       pf.setTarget(target);
      
       MessageWriter proxy = (MessageWriter)pf.getProxy();
      
       proxy.writeMessage();
   }
  
   public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
       throws Throwable{
       System.out.println("");
       System.out.println("After method: " + method.getName());
   }
}


실행결과

자기야
After method: writeMessage


'Programming > java' 카테고리의 다른 글

Types of AOP  (0) 2007/01/18
AOP 예제4 - Throws Advice  (0) 2007/01/15
AOP 예제3 - After Returning Advice  (0) 2007/01/15
AOP 예제2 - Before Advice  (0) 2007/01/15
AOP 예제1 - around advice  (0) 2007/01/15
Advice의 유형  (1) 2007/01/06
Posted by lonekim 영근
package com.youngkun.aoptest;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class SimpleBeforeAdvice implements MethodBeforeAdvice{
   public static void main(String[] args){
       MessageWriter target = new MessageWriter();
       
       ProxyFactory pf = new ProxyFactory();
       
       pf.addAdvice(new SimpleBeforeAdvice());
       pf.setTarget(target);
       
       MessageWriter proxy = (MessageWriter)pf.getProxy();
       
       proxy.writeMessage();
   }
   
   public void before(Method method, Object[] args, Object target)
       throws Throwable{
       System.out.println("Before method: "+ method.getName());
   }
}

실행 결과

Before method: writeMessage
자기야

'Programming > java' 카테고리의 다른 글

AOP 예제4 - Throws Advice  (0) 2007/01/15
AOP 예제3 - After Returning Advice  (0) 2007/01/15
AOP 예제2 - Before Advice  (0) 2007/01/15
AOP 예제1 - around advice  (0) 2007/01/15
Advice의 유형  (1) 2007/01/06
AOP 기본 개념  (1) 2007/01/04
Posted by lonekim 영근
전체 구조입니다.



MessageWriter.java
단순히 "자기야"만을 출력하는 클래스 입니다.



MessageDecorator.java
호출을 가로채서 원래 메소드가 호출되기 전에 "사랑해"를 출력하고
원래 메소드가 호출된 후에 "!"를 출력.



HelloWorldAOPExample.java
ProxyFactory를 생성하고 동시에 advice를 weaving합니다.



출력화면

'Programming > java' 카테고리의 다른 글

AOP 예제3 - After Returning Advice  (0) 2007/01/15
AOP 예제2 - Before Advice  (0) 2007/01/15
AOP 예제1 - around advice  (0) 2007/01/15
Advice의 유형  (1) 2007/01/06
AOP 기본 개념  (1) 2007/01/04
Reflection  (0) 2006/12/20
Posted by lonekim 영근
1. around advice(org.aopalliance.intercept.MethodInteceptor)
   대상메소드에 대한 호출을 가로챔
  - 대상메소드의 실제 호출 여부를 제어한다.(MethodInvocation.proceed())
  - 대상메소드의 리턴 객체를 바꿀 수 있다.(반드시 필요할 때만)

2. before advice(org.springframework.aop.BeforeAdvice)
   대상메소드가 실행되기 전에 호출됨
  - 대상메소드가 호출되지 못하도록 하려면 예외를 던질 수 있다.

3. after advice(org.springframework.aop.AfterReturningAdvice)
   대상메소드가 리턴한 후에 호출됨
  -대상메소드의 리턴값에 접근할 수 있지만 바꿀수는 없다.
  -예외를 던져서 실행흐름을 바꿀 수 있다.

4. throws advice(org.springframework.aop.ThrowsAdvice)
   대상메소드가 예외를 던질 때 호출됨

'Programming > java' 카테고리의 다른 글

AOP 예제2 - Before Advice  (0) 2007/01/15
AOP 예제1 - around advice  (0) 2007/01/15
Advice의 유형  (1) 2007/01/06
AOP 기본 개념  (1) 2007/01/04
Reflection  (0) 2006/12/20
Compose Method  (0) 2006/11/01
Posted by lonekim 영근
* 횡단(cross-cutting) 관심사

그림은 각 모듈의 공통적인 관심사를 보여준다.
공통적인 기능을 재사용하기 위해 일반적으로 상속(inheritance)나 위임(delegation)을 사용한다. 그러나 상속의 경우 동일한 기초클래스가 애플리케이션의 여러곳에서 걸쳐 사용되면 객체의 계층도를 깨뜨릴 수 있다. 또한 위임은 사용하기 번거로우며, 여전히 위임한 객체에 대한 중복호출을 필요로 한다.
AOP를 사용하면 공통적인 기능을 한곳에서 정의 할수 있으며, 새로운 기능을 적용하려고 하는 클래스를 수정할 필요 없이 그런 기능을 어디에 어떻게 적용할 것인지를 선언적으로 정의 할 수 있다.
-> 횡단 관심사는 애스팩트(aspect) 라고 하는 특별한 객체로 모듈화된다.

AOP의 장점
- 각 관심사에 대한 로직이 여기저기에 흩어지지 않고 한 장소에서 관리된다.
- 애플리케이션 고유의 서비스 모듈이 명확해 진다.


AOP 용어
aspect(area)
구현하고자 하는 횡단 관심사의 기능

joinpoint
aspect를 플러그인할 수 있는 애플리케이션의 실행지점

advice
애스팩트의 실제 구현체

pointcut
advice가 어떤  joinpoint에 적용돼야 하는지를 정의

from wikipedia


advisor
advice+pointcut

introduction
기존의 클래스에 새로운 메소드나 속성을 추가

target
advice를 받는 클래스

proxy
대상객체에 advice가 적용된 후 생성되는 객체

weaving
aspect를 대상객체에 적용하여 새로운 프로시 객체를 생성하는 과정

aspect의 적용




참조 :

'Programming > java' 카테고리의 다른 글

AOP 예제1 - around advice  (0) 2007/01/15
Advice의 유형  (1) 2007/01/06
AOP 기본 개념  (1) 2007/01/04
Reflection  (0) 2006/12/20
Compose Method  (0) 2006/11/01
미진한 설계  (0) 2006/10/30
Posted by lonekim 영근

Reflection

Programming/java 2006/12/20 17:50
Java Reflection API 에는 Reflection을 아래처럼 정의 하고 있다.
  • Determine the class of an object.
  • Get information about a class's modifiers, fields, methods, constructors, and superclasses.
  • Find out what constants and method declarations belong to an interface.
  • Create an instance of a class whose name is not known until runtime.
  • Get and set the value of an object's field, even if the field name is unknown to your program until runtime.
  • Invoke a method on an object, even if the method is not known until runtime.
  • Create a new array, whose size and component type are not known until runtime, and then modify the array's components.
또한 Java에서는 Reflection을 쓰지 않을 방법이 있으면 쓰지 말라고 한다.


Java Reflection에 대한 고찰 의 글을 보면,

Reflection에 대해 여러가지 견해들을 볼수 있다.


'Programming > java' 카테고리의 다른 글

Advice의 유형  (1) 2007/01/06
AOP 기본 개념  (1) 2007/01/04
Reflection  (0) 2006/12/20
Compose Method  (0) 2006/11/01
미진한 설계  (0) 2006/10/30
Simple FTP  (0) 2006/10/24
Posted by lonekim 영근

Compose Method

Programming/java 2006/11/01 17:36
장점과 단점
+어떤 매서드가 무슨 일을 하고, 또 그일을 어떻게 수행하는지 효과적으로 표현한다.
+동등한 수준의 작업을 하며 이름이 적절하게 붙은 몇 단계로 내부를 나눔으로써, 메서드를 단순하게 만든다.
-작은 메서드가 지나치게 많이 생길 수 있다.
-로직이 여러 곳에 흩어지기 때문에 디버깅이 어려울 수 있다.

public class  ComposeMethod
{
   public void add(Object element){
       if(!readOnly){
           int newSize = size + 1;
           if(newSize > elements.length){
               Object[] newElements = new Object[elements.length + 10];
               for(int i = 0; i < size ; i++)
                   newElements[i] = elements[i];
               elements = newElements;
           }
           elements[size++] = element;
       }
   }
}


*조건문으로 메서드의 코드 전체를 감싸기보다는, 초반에 메소드를 빠져나가도록 함으로써 메서드의 실행요건을 명시하는 것이 낫다.
public class  ComposeMethod
{
   public void add(Object element){      
       if(readOnly)
           return;
       int newSize = size + 1;
       if(newSize > elements.length){
           Object[] newElements = new Object[elements.length + 10];
           for(int i = 0; i < size ; i++)
               newElements[i] = elements[i];
           elements = newElements;
       }
       elements[size++] = element;
      
   }
}

*매직넘버 10은 그 목적을 전혀 표현하지 못하는 수자로 하드코딩되어 있으므로, 먼저 이를 상수로 변경한다.

public class  ComposeMethod
{
   private final static int GROWTH_INCREMENT = 10;

   public void add(Object element){
       if(readOnly)
           return;
       int newSize = size + 1;
       if(newSize > elements.length){
           Object[] newElements = new Object[elements.length + GROWTH_INCREMENT];
           for(int i = 0; i < size ; i++)
               newElements[i] = elements[i];
           elements = newElements;
       }
       elements[size++] = element;
      
   }
}


*elements 배열의 크기를 늘릴 필요가 있는지 검사하는 코드에 Extract Method 리팩터링을 적용한다.
public class  ComposeMethod
{
   private final static int GROWTH_INCREMENT = 10;

   public void add(Object element){
       if(readOnly)
           return;       
       if(atCapacity()){
           Object[] newElements = new Object[elements.length + GROWTH_INCREMENT];
           for(int i = 0; i < size ; i++)
               newElements[i] = elements[i];
           elements = newElements;
       }
       elements[size++] = element;
      
   }

   private boolean atCapacity(){
       return (size + 1) > elements.length;
   }
}

*elements 배열의 크기를 늘리는 코드에  Extract Method 리팩터링을 적용한다.
public class  ComposeMethod
{
   private final static int GROWTH_INCREMENT = 10;

   public void add(Object element){
       if(readOnly)
           return;       
       if(atCapacity()){
           grow();
       }
       elements[size++] = element;       
   }

   private boolean atCapacity(){
       return (size + 1) > elements.length;
   }

   private void grow(){
       Object[] newElements = new Object[elements.length + GROWTH_INCREMENT];
       for(int i = 0; i < size ; i++)
           newElements[i] = elements[i];
       elements = newElements;
   }
}

*매서드의 맨 아랫줄은 한줄 뿐이지만 다른부분과 동등한 수준이 아니다. 따라서 이 코드도 별도의 메서들 뽑아낸다.

public class  ComposeMethod
{
   private final static int GROWTH_INCREMENT = 10;

   public void add(Object element){
       if(readOnly)
           return;       
       if(atCapacity())
           grow();
       addElement(element);       
   }

   private boolean atCapacity(){
       return (size + 1) > elements.length;
   }

   private void grow(){
       Object[] newElements = new Object[elements.length + GROWTH_INCREMENT];
       for(int i = 0; i < size ; i++)
           newElements[i] = elements[i];
       elements = newElements;
   }

   private void addElement(Object element){
       element[size++] = element;
   }
}


참고 도서 : 패턴을 활용한 리팩터링

'Programming > java' 카테고리의 다른 글

AOP 기본 개념  (1) 2007/01/04
Reflection  (0) 2006/12/20
Compose Method  (0) 2006/11/01
미진한 설계  (0) 2006/10/30
Simple FTP  (0) 2006/10/24
CVS 설치 및 사용자 생성  (0) 2006/10/23
Posted by lonekim 영근
데이터 구조는 무계획하게 구축됐거나 없는 것과 마찬가지다. 모든 것이 서로 꼬여있다. 중요한 상태 데이트는 모두 전역변수에 담겨있는 것 같다. 상태 데이터가 구획화되어 있더라도 시스템의 원래 구조를 사용하지 않고 뒷구멍으로 무분별하게 넘긴다.
변수와 함수 이름은 알아보기 힘들거나 오해의 소지가 있다. 함수는 별 생각없이 정의한 긴 파라미터 목록을 가질 뿐 아니라 전역변수로 범벅이 되어 있다. 함수는 길이도 길고 복잡하게 꼬여 있을 뿐 아니라 관련없는 작업을 여러 개 수행한다.
코드는 중복되어 있다. 제어 흐름은 이해하기 어렵고 쉽게 따라갈 수도 없다. 프로그래머의 의도를 알아보는 것은 거의 불가능하다. 코드는 읽을 수도 없고 해독도 불가능해 보인다.
많은 사람의 손을 거치며 여러 번 패치된 흔적이 보이며, 작업자들은 그들의 작업이 어떤 결과를 초래하는지 거의 이해하지 못한 것 같다.


출처 : Big Ball of Mud

'Programming > java' 카테고리의 다른 글

Reflection  (0) 2006/12/20
Compose Method  (0) 2006/11/01
미진한 설계  (0) 2006/10/30
Simple FTP  (0) 2006/10/24
CVS 설치 및 사용자 생성  (0) 2006/10/23
HTML 특수문자  (0) 2006/10/23
Posted by lonekim 영근

Simple FTP

Programming/java 2006/10/24 11:19
Download simpleftp.jar

import org.jibble.simpleftp.*;

try {    
SimpleFTP ftp = new SimpleFTP();

// Connect to an FTP server on port 21.
ftp.connect("ftp.somewhere.net", 21, "username", "password");

// Set binary mode.
ftp.bin();

// Change to a new working directory on the FTP server.
ftp.cwd("web");

// Upload some files.
ftp.stor(new File("webcam.jpg"));
ftp.stor(new File("comicbot-latest.png"));

// You can also upload from an InputStream, e.g.
ftp.stor(new FileInputStream(new File("test.png")), "test.png");
ftp.stor(someSocket.getInputStream(), "blah.dat");

// Quit from the FTP server.
ftp.disconnect();




}catch (IOException e) {
// Jibble.
}

'Programming > java' 카테고리의 다른 글

Compose Method  (0) 2006/11/01
미진한 설계  (0) 2006/10/30
Simple FTP  (0) 2006/10/24
CVS 설치 및 사용자 생성  (0) 2006/10/23
HTML 특수문자  (0) 2006/10/23
바보같은 스크립트 에러1.  (0) 2006/10/23
Posted by lonekim 영근
TAG ftp, 자바

http://www.cvsnt.com 에서 설치 실행 파일을 다운 받는다.


Typical installation 을 선택하여 설치한다.


제어판에 보면  cvs server라는 아이콘이 생성된 것을 확인 할수 있다.


더블클릭해서 리포지터리를 추가한다.


Location:

D:/cvs

Name:

/cvs


이렇게 하고 확인을 누르면

D:/cvs 디렉토리가 생기고 그하위에 CVSROOT라는 디렉토리가 생성된다.


커맨드 창에서 환경변수 설정

C:\>set CVSROOT=:pserver:127.0.0.1:/cvs


로그인

C:\>cvs login
Logging in to :pserver:Administrator@127.0.0.1:2401:/cvs
CVS Password: *****


사용자 추가

cvs passwd -a -r <OS 사용자 이름> <CVS 사용자 이름>

C:\>cvs passwd -a -r cvsuser cvs1
Adding user cvs1@127.0.0.1
New Password: *****
Verify Password: *****


* OS사용자는 administrator 보다 cvs 전용사용자를 생성하여 사용하는 것을 권장


C:\>cvs passwd -a -r cvsuser cvs2
Adding user cvs2@127.0.0.1
New Password: *****
Verify Password: *****

'Programming > java' 카테고리의 다른 글

미진한 설계  (0) 2006/10/30
Simple FTP  (0) 2006/10/24
CVS 설치 및 사용자 생성  (0) 2006/10/23
HTML 특수문자  (0) 2006/10/23
바보같은 스크립트 에러1.  (0) 2006/10/23
JAVA performance tips  (0) 2006/10/23
Posted by lonekim 영근

예전에 메모의 기술이라는 책에서 본 글귀가 생각이 난다.

잊어버리기 위해서 메모하자!


http://w3schools.com/tags/ref_symbols.asp

     &nbsp; 공백문자

>    &gt; 부등호
<    &lt; 부등호
&    &amp; AND
§     &#167; section

'Programming > java' 카테고리의 다른 글

Simple FTP  (0) 2006/10/24
CVS 설치 및 사용자 생성  (0) 2006/10/23
HTML 특수문자  (0) 2006/10/23
바보같은 스크립트 에러1.  (0) 2006/10/23
JAVA performance tips  (0) 2006/10/23
"equals()"와 "=="의 차이점  (0) 2006/10/23
Posted by lonekim 영근

for(int i, int j = AAA.length; i <j ; i++){

  ...

)


오늘 코딩하면서 for문에서 "{" 를 열고 ")"로 닫아줘서 스크립트 에러가 계속 생겼다.


집중력이 부족한 탓인지 찾는데 많은 시간이 걸렸다.


그리고 스크립트에서 for문을 쓰는데 변수선언을 int로 해버려서


한참을 해맸다.


for(var i, var j = AAA.length; i <j ; i++){

  ...

}


다음에 또 이런 실수를 할까봐 노파심에 기록해본다...

'Programming > java' 카테고리의 다른 글

CVS 설치 및 사용자 생성  (0) 2006/10/23
HTML 특수문자  (0) 2006/10/23
바보같은 스크립트 에러1.  (0) 2006/10/23
JAVA performance tips  (0) 2006/10/23
"equals()"와 "=="의 차이점  (0) 2006/10/23
코드속의 나쁜 냄새  (0) 2006/10/23
Posted by lonekim 영근

Java Press (http://www.gihyo.co.jp/magazines/javapress) 라는 일본의 Java전문 서적(2003년 2월판)에서 발췌한 Java performance tips입니다.

그중 Java 일반적사항에 관련하여 7개, String 관련2개, Collection관련 8개, IO관련2개,
등 총 4개 분야 19여개의 Tips에 대해 설명하겠습니다.

1. 일반적사항 관련 Tips

① 쓸데없이 Cast를 남발하면 바람직하지 않음.

Loop구조에서 쓸데없이 cast를 남발하면 performance를 현저히 저하시킵니다.

예) 쓸데없이 cast를 남발한 바람직하지 않은 코드예

for(int i=0; i<list.size(); i++)
{
if ( ((String)list.get(i)).indexOf('a') ! =-1) {
} else if(((String)list.get(i)).indexOf('b') ! =-1) {
} else if(((String)list.get(i)).indexOf('c') ! =-1) {
} else if(((String)list.get(i)).indexOf('d') ! =-1) {
} ...
}

예) 쓸데없는 cast를 제거한 좋은 코드예

for (int i=0; i<list.size(); i++)
{
String value = (String)list.get(i);
if(value.indexOf('a') ! = -1) {
} else if ((value.indexOf('b') != -1){
} else if ((value.indexOf('c') != -1){
} else if ((value.indexOf('d') != -1){
} ...
}

② 쓸데없이 동기화를 행하면 바람직하지 않음

同期化(Synchronized)은 높은 cost입니다. 필요가 없을 시에는 사용하지 마십시요.


③ 쓸데없는 인스턴스생성은 바람직하지 않음

인스턴스수가 많지 않은 경우에는 별 문제가 되지 않겠지만, 많은 인스턴스를 생성
하는 경우에는 performance를 현저히 저하 시키므로 주의하십시요.

예) String 인스턴스를 2번생성한 바람직 하지 않은 코드예

String value = new String("문자열");

예) 개량 후 코드예

String value = "문자열";


④ 필요이상으로 Wrapper클래스를 사용하면 바람직하지 않음

Wrapper클래스(Integer, Boolean 등)을 클래스멤버로 사용하는 경우 인스턴스생성
이 필요하게 되므로, 기본적으로 Primitive형을 사용하는 편이 performance를 높
입니다.

예) Wrapper클래스를 사용한 코드예

public class Person {

private Integer id;
private Boolean isValid;
};

예) primitive형으로 치환한 코드예

public class Person {

private int id;
private boolean isValid;
};

또한 Wrapper클래스에는 없지만 java.math.BigDecimal 클래스는 Double 클래스
보다 정확한 부동소수연산이 가능하지만 performance를 저하시키므로 유의바랍니
다.

⑤ primitive형의 default값을 이용

int형 boolean형등의 primitive형은 선언시 default값이 초기화 됩니다. 이것을 이용하면 초기화처리를 생 략할 수 있습니다. 덧붙여 말하면 int형은 0, float은 0.0, boolean형은 false로 선언시에 초기화 됩니다.

예) primitive형의 초기화처리를 행한 코드예

public class Person {

private int id;
private boolean isValid;

public Person() {

id = 0;
isValid = false;
}
}

예) primitive형의 default값을 이용한 코드예

public class Person {

private int id;
private boolean isValid;

public Person() {

}
}


⑥ 문자열을 숫자형으로 변환하는 방법

문자열을 숫자형으로 변환시에 각 Wrapper클래스(Integer,Double 등)의 static 메
소드인 parseXXX()를 이용합니다.
valueOf()를 경유해서 XXXValue()를 실행하면 한번의 인스턴스를 생성하게 되어
불필요한 cost를 들게 합니다.

예) valueOf()를 이용하여 문자열을 숫자형으로 변환한 코드예

double doubleValue = Double.valueOf("1234.56").doubleValue();
int intValue = Integer.valueOf("123456").intValue();

예) 개량한 코드예

double doubleValue = Double.parseDouble("1234.56");
int intValue = Integer.parseInt("123456");


⑦ 필요이상으로 System.gc()를 사용하면 바람직하지 않음

필요이상으로 System.gc()를 이용하면 프로그램실행 performance가 저하됩니다.




2. String 관련 Tips

① 문자열 연결방법
+연산자를 이용하여 문자열을 연결하게 되면 심하게 performance가 저하됩니다.
StringBuffer클래스를 사용하면 performance가 향상됩니다.

예) + 연산자에 의한 문자열연결 코드예

String result = "";
for (int i=0; i<loopNum; i++ ) {
result + =i;
}
예) StringBuffer클래스에 의한 문자열연결 코드예

StringBuffer buf = new StringBuffer();
for(int i=0; i<loopNum; i++) {
buf.append(i);
}
String result = buf.toString();

더욱이, 연결후의 문자열의 길이를 알고 있을 경우, StringBuffer클래스 생성시에
적당한 초기값을 주면 더욱더 performance가 향상됩니다.
StringBuffer클래스는 용량이 부족하게 되면 내부적으로 버퍼사이즈가 자동으로 변
경되나 연결후의 사이즈를 알고 있는 경우에는 초기값으로 사이즈를 주면 그러한
처리과정을 생략할 수 있습니다.

예) StringBuffer buf = new StringBuffer(length);

표) 문자열연결에 관한 performance 측정

연결수: 1000 연결수 : 500
+연산자 250(ms) 7500(ms)
StringBuffer 15(ms) 20(ms)
StringBuffer(초기값有) 2(ms) 10(ms)
CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1

② StringTokenizer클래스

문자열을 자를 때,StringTokenizer클래스를 이용하는 것이 편하기는 하지만 문자열
이 고정되어 있는 경우에는 독자적인 Tokenizer를 사용하는것이 효율적입니다.

StringTokenizer클래스가 token을 반복할때, 매번 자를문자가 변경되어 있는지를
체크하기 때문입니다.

예) StringTokenizer클래스를 취하는 코드예

String word = "aaa,bbb,ccc,ddd,eee,fff";

StringTokenizer token = new StringTokenizer(word,",");

List list = new ArrayList();

while(token.hasMoreTokens()) {
list.add(token.nextToken());
}

예) 자를문자를 ‘,’로 고정한후 token을 추출한 코드예

String word = "aaa,bbb,ccc,ddd,eee,fff";

List list = new ArrayList();

int now=0;
int next=0;

while ( (next = word.indexOf(",",now)) > 0 )
{
list.add(word.substring(now,next));
now = next + 1;
}


또한 StringTokenizer클래스에는 hasMoreElements()와 hasMoreTokens() 두개의
메소드가 있는데, hasMoreElements()가 내부적으로 hasMoreTokens()를 호출하
므로 통상적으로 hasMoreTokens()를 이용 하도록 합니다.

참고) J2SE 1.4부터 새로운 메소드가 추가된것이 있는데, SringTokenizer 클래스의
token 추출과 같은 기능의 메소드로 java.lang.String 클래스의 split()메소드를 소
개합니다.

String word = "aaa,bbb,ccc,ddd,eee,fff";
String [] result = word.split(",");

3. Collection관련 Tips

① 배열의 이용

데이타의 개수나 사이즈가 변동하는 경우에만 Collection계통의 클라스를 사용하며,
그외에는 배열을 사용합니다.

② J2SE1.2이상에서의 Collection이용

JDK1.1까지는 Vector클래스나 Hashtable클래스가 편리했으나, 이러한 클래스는 메소드가 동기화(synchronized)
되어 있습니다. 따라서 동기화가 필요없는 경우에는 비효율적입니다.
J2SE1.2이상에서는 메소드가 동기화되어있지 않은 ArrayList클라스나 HashMap클
래스를 이용합니다.
Vector클래스는 ArrayList로 Hashtable은 HashMap클래스로 바꿔이용합니다.

예) 구 Collection클래스 이용예

Vector vector = new Vector();
Hashtable table = new Hashtable();

예) J2SE1.2이상 Collection클래스 이용예

List list = new ArrayList();
Map map = new HashMap();

또한, J2SE1.2이상에서 Collection의 동기화가 필요한 경우에는

List list = Collection.synchronizedList(new ArrayList(..));

위와 같이 사용합니다.

③ Collection size 초기화

Collection을 default 사이즈로 만들면, 필요시 자동적으로 사이즈가 확장되나 명확히 예측이 가능한 경우에는 사이즈를 초기화 하는 편이 훨씬 효율적입니다.

예) 사이즈를 지정하지 않고 Collection을 생성한 코드예

List list = new ArrayList();
HashMap map = new HashMap();

예) 사이즈를 지정한 Collection 생성 코드예

List list = new ArrayList(num);
HashMap map = new HashMap(num);


④ Iterator클래스보다 빠른 요소검사

Collection 사이즈를 명확히 알 경우에는 Iterator클래스의 next()와 비교하여,
Iterator클래스의 hasNext()에 의한 요소종료 체크가 필요없으며 내부처리가 간단한
List클래스의 get()메소드를 추천합니다.

예) Iterator클래스의 next()에 의한 요소조사

Iterator iterator = array.iterator();
while (iterator.hasNext())
{
Object object = iterator.next();
}

예) List클래스의 get()에 의한 요소조사

int size =array.size();
for (int i=0; i<size ; i++)
{
Object object = array.get(i);
}

⑤ 요소삽입/삭제시 주의점

List도중에 요소를 추가/삭제할 경우에 내부적으로 배열의 copy가 행해집니다.
따라서 요소의 수가 많으면 많을 수록 copy하는 요소수도 많아져 결과적
으로 performance의 저하를 초래합니다.
내부적처리로써 [ (전체사이즈) - (삽입/삭제대상요소의 index)] 만큼의 요소가 copy되므로 아래의 예를 참조바랍니다.

예) List의 맨앞에 요소를 추가/삭제하는 경우 -- 속도가 느림.

list.add(0, new Object());
list.remove(0);

예) List의 맨 뒤에 요소를 추가/삭제하는 경우 -- 속도가 빠름.

list.add(new Object());
list.remove(list.size() - 1);


⑥ List요소 전체삭제

List요소를 전체삭제 할때, 통상 쓰는 clear()을 이용하지말고, 새롭게 List를 생성(초기화)하는 편이 효율적입니 다. 왜냐하면, clear()는 내부적으로 보유하고 있는 배열의 전체요소에 null을 셋팅함으로써 전체삭제를 실현하기 때문입니다.

예) clear()에 의한 요소 전체삭제

List list = new ArrayList();

for(int i=0; i< num; i++) {
list.add(new Integer(i));
}

list.clear();

예) List재작성에 의한 요소 전체삭제

List list = new ArrayList();

for(int i=0; i< num; i++) {
list.add(new Integer(i));
}

list = new ArrayList();

⑦ 배열요소 copy방법

루프를 돌며 배열요소를 하나씩 copy할 경우에는 System.arraycopy(Object src,int srcPos,Object dest,int destPos,int length)를 이용합니다.
메소드의 인자는 아래와 같습니다.

src - the source array.
srcPos - starting position in the source array.
dest - the destination array.
destPos - starting position in the destination data.
length - the number of array elements to be copied.

예) 루프를 돌며 배열소소를 copy하는 예

int[] buf = new int[num];
int[] copy = new int[num];

for (int i=0; i<num; i++)
{
copy[i] = buf[i];
}

예) System.arraycopy()에 의한 신속한 copy 예

int[] buf = new int[num];
int[] copy = new int[num];

System.arraycopy(buf,0, copy,0, num);

⑧ List에 보존되어 있는 object 요소를 배열에 넣는 방법

List클래스의 toArray()를 이용하여 List에 보존되어 있는 Object요소를 배열에 넣습니다.

예) 루프에 의한 object요소 copy 예

int size = list.size();
Integer[] result = new Integer[size];

for (int i=0; i<size; i++)
{
result[i] = (Integer) list.get(i);
}

예) toArray()에 의한 신속한 copy

int size = list.size();
Integer[] result = new Integer[size];

list.toArray(result);





4. IO관련 Tips

① 통상적으로 Stream계의 클래스를 사용함

java.io패키지에서 문자데이터 입출력시에는 Reader/Writer 클래스를
바이트단위 데이터 입출력시에는 InputStream/OutputStream 을 이용합니다.
다만, 아스키캐릭터의 경우에는 1문자가 1바이트이므로
InputStream/OutputStream 클래스를 이용할 수 있습니다.

약 100K 정도의 영문자로 이루어져 있는 텍스트파일을 가지고 예를 들겠습니다.

예) Reader계 클래스을 이용한 파일 입출력 예

FileReader in = new FileReader("test.txt");
int buf;

while ( buf = in.read() != -1)
{
.......
}
in.close();

예) InputStream계 클래스를 이용한 파일 입출력 예

FileInputStream in = new FileInputStream("test.txt");
int buf;

while ( buf = in.read() != -1)
{
.......
}

in.close();

위의 2가지 예를 비교한 performance 비교표는 아래와 같습니다.

사용클래스 처리시간(ms)
FileReader 18000
FileInputStream 800
CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1

InputStream계 클래스를 이용한 파일 입출력이 월등히 빠른 처리속도를 보임을 알 수 있습니다.

② Buffering을 이용

예) Buffering을 한 Reader계 클래스을 이용한 파일 입출력 예

FileReader in = new FileReader("test.txt");
BufferedReader bin = new BufferedReader(in);
int buf;

while ( buf = bin.read() != -1)
{
.......
}

bin.close();

예) Buffering을 한 InputStream계 클래스를 이용한 파일 입출력 예

FileInputStream in = new FileInputStream("test.txt");
BufferedInputStream bin = new BufferedInputStream(in);
int buf;

while ( buf = bin.read() != -1)
{
.......
}
bin.close();

위의 2가지 예를 비교한 performance 비교표는 아래와 같습니다.

사용클래스 처리시간(ms)
BufferedReader 150
BufferedInutStream 80
CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1


- the end-


출처 : http://java.lin4u.com/my/view.php?idx=79

'Programming > java' 카테고리의 다른 글

HTML 특수문자  (0) 2006/10/23
바보같은 스크립트 에러1.  (0) 2006/10/23
JAVA performance tips  (0) 2006/10/23
"equals()"와 "=="의 차이점  (0) 2006/10/23
코드속의 나쁜 냄새  (0) 2006/10/23
Joel Test : 나은 코딩을 위한 12단계  (0) 2006/10/23
Posted by lonekim 영근


티스토리 툴바