[Spring] @Autowired의 Before/After

Posted at 2009/04/29 15:35// Posted in 나만의 작업/Spring


알고있는 내용이기에~ 그냥 가볍게 Before 와 After code

Before - @Autowired annotation이 없었을 때 

applicationContext.xml에서 설정
<bean id="empDao" class="EmpDao" /> <bean id="empManager" class="EmpManager"> <property name="empDao" ref="empDao" /> </bean>

EmpDao의 bean을 inject
public class EmpManager { private EmpDao empDao; public EmpDao getEmpDao() { return empDao; } public void setEmpDao(EmpDao empDao) { this.empDao = empDao; } ... }

이랬던 코드가~ 바뀐다. 

After

applicationContext.xml에서 설정

<context:annotation-config /> <!-- 요거 꼭 빼먹지 말것 --> <bean id="empManager" class="autowiredexample.EmpManager" /> <bean id="empDao" class="autowiredexample.EmpDao" />

import org.springframework.beans.factory.annotation.Autowired; public class EmpManager { @Autowired private EmpDao empDao; }

Annotation을 써서 훨씬 보기에 간결한 코드를 짤 수 있다.


출처 - http://flyburi.com/446

===================================================================================

특정 Bean의 기능 수행을 위해 다른 Bean을 참조해야 하는 경우 사용하는 Annotation으로는 @Autowired 또는 @Resource가 있다.

  • @Autowired

  • Spring Framework에서 지원하는 Dependency 정의 용도의 Annotation으로, Spring Framework에 종속적이긴 하지만 정밀한 Dependency Injection이 필요한 경우에 유용하다.
  • @Resource

  • JSR-250 표준 Annotation으로 Spring Framework 2.5.* 부터 지원 가능한 Annotation이다. Annotation 사용으로 인해 특정 Framework에 종속적인 어플리케이션을 구성하지 않기 위해서는 @Resource를 사용할 것을 권장한다. @Resource를 사용하기 위해서는 클래스패스 내에 jsr250-api.jar 파일이 추가되어야 함에 유의해야 한다.
다음은 @Resource를 사용한 예이다.
@Service
public UserServiceImpl implements UserService {
    @Resource
    private UserDAO userDAO;
}

@Autowired와 @Resource를 사용할 수 있는 위치는 다음과 같이 약간의 차이가 있으므로 필요에 따라 적절히 사용하면 된다.
  • @Autowired : 필드, 생성자, 입력파라미터가 여러개인 메소드(@Qualifier는 메소드의 파라미터)에 적용 가능
  • @Resource : 필드, 입력 파라미터가 한 개인 빈 프로퍼티 setter 메소드에 적용가능
@Autowired나 @Resource를 필드에 직접 정의하는 경우 별도 setter 메소드는 정의하지 않아도 된다.

@Autowired

@Autowired는 기본적으로 type-driven injection 이다. 타입으로 참조할 빈을 찾았을 때 같은 타입의 빈이 여러 개 검색되었을 경우, @Qualifier annotation을 사용하여 구분할 수 있도록 해준다. 

다음은 @Qualifier를 사용한 예이다.
@Service
public ProductService {
    @Autowired
    @Qualifier("electronics")
    private ProductCategory productCategory;
}
Qualifier를 정의하는 방법에는 다음과 같이 두가지가 있다.
  • XML을 사용한 정의
  • <bean class="anyframe.sample.springmvc.annotation.web.SimpleProductCategory">
        <qualifier value="electronics"/>
        <!-- inject any dependencies required by this bean -->
    </bean>
    
    <bean class="anyframe.sample.springmvc.annotation.web.SimpleProductCategory">
        <qualifier value="cosmetics"/>
        <!-- inject any dependencies required by this bean -->
    </bean>
    		
  • Annotation을 사용한 정의
  • @Component
    @Qualifier("electronics")
    public class ElectronicsProductCategory implements ProductCategory {
    	//...
    }

기본적으로 @Autowired가 적용된 프로퍼티는 필수이기 때문에 반드시 해당 빈이 존재해야 하지만, required 속성을 false로 설정하는 경우에는 해당되는 Bean을 찾지 못하더라도 에러가 발생하지 않는다.
@Service
public UserService implements UserService {
    @Autowired(required=false)
    private UserDAO userDAO;
}

@Resource

@Resource annotation은 다음과 같은 경우에 사용한다.
  • Bean name으로 Dependency Injection을 하고자 하는 경우
  • Type-driven injection을 할 수 없는 Collection이나 Map 타입의 빈
@Resource를 사용하는 경우 참조되는 Bean은 변수명을 Bean Name으로 하여 Spring 컨테이너에 의해 자동으로 인지되는데, 변수명을 이용하여 참조 관계에 놓인 Bean을 찾았는데 해당 Bean이 없는 경우에는 클래스 타입을 이용하게 된다. 참조 관계에 놓인 Bean의 Name을 직접 명시하고자 하는 경우에는 다음과 같이 'name' 속성을 부여할 수 있다.
@Service
public UserServiceImpl implements UserService {
    @Resource (name="uDAO")
    private UserDAO userDAO;
}

Custom Qualifier

@Autowired annotation을 이용하여 보다 정밀하게 Dependency Injection을 수행할 필요가 있을 경우, Spring Framework의 Custom Qualifier를 사용할 수 있다.
1.Custom Qualifier 정의
다음은 @UserDAOQualifier라는 Custom Qualifier 코드의 일부로 @UserDAOQualifier는 dbtype이라는 속성 정보를 갖고 있다. dbtype 따라 참조해야 할 Bean이 달라지는 경우 즉, DBMS 유형에 따라 다른 데이터 접근 로직이 실행되어야 하는 경우에 사용될 수 있다.
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention (RetentionPolicy.RUNTIME)
@Qualifier
public @interface UserDAOQualifier {
    String dbtype();
}
java.lang.annotation.Target은 사용한 Annotation이 어디에 적용될 것인지 Annotation을 선언할 때 정의한다. (예를 들면 클래스나 메소드, 필드 등.) 만약 Target이 정해지지 않으면 어디에서나 사용가능한 Annotation이 된다. java.lang.annotation.Retention은 Annotation을 선언할때 쓰이는데, 다음과 같은 Parameter들이 사용 가능하다.
  • RetentionPolicy.SOURCE : 해당 Annotation이 소스레벨이라는 사실을 알려줌 (default)
  • RetentionPolicy.CLASS : 소스코드와 컴파일된 클래스 파일에는 사용 가능하지만, 런타임에는 사용 불가.
  • RetentionPolicy.RUNTIME : 소스코드, 컴파일된 코드, 런타임에도 사용 가능

2.XML 정의
속성 정의 XML 파일 내에 Custom Qualifer로써 UserDAOQualifier 클래스에 대해 정의하여 특정 클래스에서 해당 Annotation을 사용할 수 있도록 한다.
<bean id="customAutowireConfigurer"
    class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
    <property name="customQualifierTypes">
        <set><value>…UserDAOQualifier</value></set>
    </property>
</bean>
다음은 dbtype에 따라 어떤 Bean이 할당될 것인지를 명시하는 부분으로 dbtype이 Oracle일 경우 UserDAOWIthOracle의 인스턴스가 컨테이너에 의해 인지되도록 정의되어 있음을 알 수 있다.
<bean class="...UserDAOWIthOracle">
    <meta key="dbtype" value="oracle"/>
</bean>

3.활용
앞서 정의한 Custom Qualifier @UserDAOQualifier는 다음과 같이 사용한다. 다음의 코드에서 dbtype을 oracle로 정의하고 있으므로, xml 정의에 따라 userDAO라는 변수에는 UserDAOWIthOracle의 인스턴스가 할당될 것이다.
public class UserServiceImpl implements UserService {
    @Autowired
    @UserDAOQualifier(dbtype="oracle")
    private UserDAO userDAO;
    // ...
}


출처 - http://dev.anyframejava.org/anyframe/doc/core/3.2.1/corefw/guide/annotation-dependencies.html


===================================================================================


@Autowired 이라는 단어를 그대로 풀이하자면 자동으로 와이어링을 해주겠다는 것이다.

이는 XML(ApplicationContext)에 따로 빈을 작성해서 DI해주는 작업을 하는 대신에 DI받고자 하는 객체나 메소드에 Autowired 어노테이션을 명시적으로 작성한다. Autowired 어노테이션을 객체나 메소드의 앞에 명시적으로 작성했다면 해당 객체가 DI를 받기 위해 setter 메소드를 작성해서 사용할 필요가 없다. DI를 받기 위해 존재해야 하는 것이 setter 메소드라는 존재인데 이는 XML에서 DI를 해서 빈을 넘겨주면 *.java 파일에서 빈을 받기 위해 생성자나 setter 메소드가 필요한 것인데 Autowired 어노테이션이 이 작업을 하지 않아도 된다고 알려주는 것이다.

단, Autowired 어노테이션을 사용하기 위해 XML에 별도의 설정이 필요하다.
XML(ApplicationContext)에 <context:annotation-config/> 작성


--Before--

public class BoardController {
private BoardService boardService;
public void setBoardService(BoardService boardService) {
this.boardService = boardService;
}

public BoardService getBoardService() {
return boardService;
}
...
}

<bean id="boardController" class="board.controller.BoardController">
<property name="boardService" ref="boardServiceImpl" />
</bean>
프로퍼티에 boardServiceImpl로 등록이 되어 있는데 이는 빈으로 따로 작성



--After--

public class BoardController {
@Autowired
private BoardService boardService;
...
}

<context:annotation-config/>    
<bean id="boardController" class="board.controller.BoardController"/>

DI를 받으려고 하는 bean도 작성
작성해주지 않으면 DI받으려고 할때 bean을 찾지 못한다고 에러메시지 출력
<bean id="boardServiceImpl" class="board.service.BoardServiceImpl"/>


----------------------------------------------------------------------------------------------------------------------------------------


<context:component-scan bace-package="패키지">
  <context:exclude-filter type="annotation" 
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

이와 같은 설정을 통해 @Autowired하려는 모든 빈을 등록해줄 수 있다. 이 설정은 base-package로 등록해 놓은
패키지에 존재하는 어노테이션을 명시해 놓은 클래스나 메소드, 변수 등을 별도의 설정이나 등록 없이 사용해 줄 수 있다. 
예를 들어 @Autowired하려는 변수에 객체를 빈을 통해 주입하는 방식을 위의 설정을 통해 조금은 설정이 편리해진다.
빈을 DI 받기 위한 여타의 작업들을 할 수고를 덜어준다.


출처 - http://luckychips.egloos.com/1629118


===================================================================================


어노테이션은 자바 1.5부터 지원한다.

스프링2는 어노테이션을 이용하여 빈과 관련된 정보를 설정할 수 있다.

 

@Required

org.springframework.beans.factory.annotaion패키지에 에 있으며 스프링 2부터 제공되고 필수 프로퍼티를 명시할때 사용된다.

 

@Required를 이용하여 필수 프로퍼티를 설정

1단계 : 코드내에 프로퍼티 설정 메서드에 @Required 어노테이션을 붙인다.

 

import org.springframework.beans.factory.annotation.Required

public class TestBean {

    private TestDao testDao;

 

    @Required

    public void setTestDao(TestDao testDao) {

        this.testDao = testDao;

    }

}

 

2단계 : 스프링 설정 파일에 RequiredAnnotationBeanPostProcessor클래스를 빈으로 등록

 

<bean class="org.springframework.beans.factory.annotaion.RequiredAnnotationBeanpostProcessor"/>

<bean name="testBean"  class="lja.test.TestBean">

    <property name="testDao" ref="testDao"/> <!--@Required 어노테이션을 적용하였으므로 설정하지 않으면 예외를 발생시킨다.-->

</bean>

 

RequiredAnnotationBeanPostProcessor 클래스는 스프링 컨테이너에 등록된 bean객체를 조사하여 @Required 어노테이션으로 설정되어 있는 프로퍼티의 값이 설정되어 있는지 검사하고 설정되어있지 않으면 bean생성시 예외를 발생시킨다.

 

 

RequiredAnnotationBeanPostProcessor 클래스를 빈으로 등록하지 않고

<context:annotation-config>태그를 이용할 수도 있다.

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:context="http://www.springframework.org/schema/context"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans-2.5xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config/>

</beans>

 

@Autowired

의존관계를 자동으로 설정해주는 어노테이션

: 타입을 이용하여 의존객체를 자동으로 설정한다.

: 생성자, 필드, 메서드 세곳에 적용 가능하다.

 

예) 프로퍼티 설정 메서드 이용

import org.springframework.beans.factory.annotation.Required

public class TestBean {

    private TestDao testDao;

 

    @Autowired

    public void setTestDao(TestDao testDao) {

        this.testDao = testDao;

    }

}

위와 같은 경우 testDao프로퍼티에 TestDao 타입의 bean객체를 전달한다.

AutowiredAnnotationBeanPostProcessor 클래스를 설정파일에 빈객체로 등록하면 @Autowired 어노테이션을 이용한 자동설정이 적용된다.

 

또한 Required어노테이션과 마찬가지로 <context:annotation-config>태그를 사용하면 된다.

@Autowired 어노테이션은 프로퍼티 설정 메서드 뿐 아니라 일반 메서드나 멤퍼필드 자체에 적용시킬수도 있다.

제너릭이 적용된 컬렉션 타입에도 적용시킬 수 있다.

 

@Autowired 어노테이션은 타입을 이용하여 자동으로 빈객체를 전달하기 때문에 타입에 맞는 객체가 없거나 두개 이상일 경우 예외를 발생시킨다.

 

@Autowired 어노테이션을 적용한 프로퍼티를 반드시 설정할 필요가 없는 경우에는 @Autowired 어노테이션의 required속성 값을 false로 지정한다.

@Autowired(required=false)

 

이렇게 지정된 경우에는 해당 타입에 맞는 빈객체가 존재하지 않는다고 해도 예외를 발생시키지는 않는다.

 

@Qualifier

: 동일한 타입의 빈객체들 중 특정 빈 객체를 자동으로 설정하도록 한다.

: @Autowired 어노테이션과 함께 사용되며 자동 연결될 빈객체의 수식어를 값으로 갖는다.

 

public class TestBean {

    @Autowired

    @Qualifier("main")

    private TestDao testDao;

}

위 코드에서 수식어구는 main 이고

이러한 수식어는 설정파일에서 <qualifer> 태그를 이용하여 설정한다.

 

<bean id="testDao" class="lja.test.TestDao">

    <qualifier value="main"/>

</bean>

 

@Resource

:javax.annotation 패키지에 위치한 어노테이션

:자바 6버전 및 JEE5 버전에 추가된 것으로 어플리케이션에서 필요로 하는 자원을 자동 연결할 때 사용

:스프링 2.5 부터 지원하는 어노테이션으로 스프링에서는 의존하는 빈객체를 전달할 때 사용하다.

:name속성에 자동으로 연결될 빈객체의 이름을 입력한다 @Resource(name="testDao")

:CommonAnnotationBeanPostProcessor 클래스를 설정파일에 빈객체로 등록하여 어노테이션을 적용시킨다.

<bean class="org.springframework.beans.factory.annotation.CommonAnnotationBeanPostProcessor"/>

혹은 <context:annotation-config>태그를 이용한다.

 

 

[출처] http://blog.naver.com/dikalee/140088444257 

Posted by linuxism
,