어노테이션 개념
어노테이션은 환경설정에 관한 xml에 사용되며 자바코딩의 간결화를 시켜주어 코드대신 사용이 가능하다.
어노테이션의 장점
어노테이션의 단점
어노테이션과 관련된 클래스와 같이 연동->이해하기가 쉽지않다.
어노테이션 은 메타정보가 소스코드에 들어가므로 파악하기 어려움
(재 컴파일이 필요하다.)
소스코드가 같이 제공되지 않으면 사용에 제약이 따름
(어노테이션 과 클래스 같이 사용할것)
@Required
@Required를 적용한 메서드를 반드시 호출해야되는데 만약에 호출하지 않으면 에러를 유발시킨다.
예제를 통해 정리하고자 한다.
1. Camera.java 생성
-@Required적용
package anno1;
import org.springframework.beans.factory.annotation.Required;
public class Camera extends Object{// 모든객체는 extends Object를 생략하고있다
private int number;//카메라수 0
@Required
public void setNumber(int number) {
this.number = number;
System.out.println("setNumber() call");
}
//메서드이름 위에 기술=>메서드명이 오버라이딩이 된 메서드인지 확인해주는 기능을 가진 어노테이션
@Override
public String toString() {
// TODO Auto-generated method stub
return "Camera[number="+number+"]";
}
}
app2.xml 내용추가
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean id="camera" class="anno1.Camera">
<property name="number" value="30" />
</bean>
만약 property를 주석처리하거나 지우면 @Required로인해 number값은 null이 아니라 에러가 뜬다.
3. Main.java
-이전꺼에서 id값과 클래스명만 수정해준다.
package anno1;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여 // xml이 여러개면 ,로 쭉쭉 나열 가능
String [] configLocation=new String[] {"app2.xml"};
//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
AbstractApplicationContext context=
new ClassPathXmlApplicationContext(configLocation);
//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정
context.registerShutdownHook();
//4.xml에서 만들어진 객체를 가져와서 처리
//형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
Camera camera=
context.getBean("camera",Camera.class);
System.out.println("camera=>"+camera);//10
//5.context도 종료
context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
}
}
@Autowired
@Autowired가 붙으면 해당 변수 또는 메서드의 타입을 체크한후 그 타입의 객체가 메모리에 존재하는지를 확인한 후레 그 객체를 변수에 주입한다.
생성자나 메소드, 멤버변수 위에 모두 사용할수 있다.
=>주로 멤버변수 위에 선언한다
차이점
메서드에 적용 =>자동으로 객체를 넣어줌
멤버변수에 적용 =>Setter Method가 필요없다.(코딩양이 줄어들어 개발시간이 단축)
예제를 통해 정리하고자 한다.
package anno2;
//문자전송 시스템
public class SmsSender {}
package anno2;
import javax.inject.Inject;
//문자를 전송=>기간을 정하기
public class SystemMoniter {
private long periodTime;//기간
//has a 관계 =>두 클래스가 연결
//@Autowired
private SmsSender sender;
//Setter Method
public void setPeriodTime(long periodTime) {
this.periodTime = periodTime;
System.out.println("setPeriodTime() call");
}
@Required
@Autowired
public void setSender(SmsSender sender) {
this.sender = sender;
System.out.println("setSender() call=>"+sender);
}
@Override
public String toString() {// Setter메서드로 잘 설정됐는지 확인할수있음
// TODO Auto-generated method stub
return "SystemMoniter[periodTime="+periodTime+",sender="+sender+"]";
}
}
3. app2.xml 내용추가
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<!-- @Autowired로 인해 property태그 또는 p네임스페이스를 생략해도 적용된다 -->
<bean id="moniter" class="anno2.SystemMoniter" />
<bean id="sender" class="anno2.SmsSender" />
4. Main 생성
package anno2;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여 // xml이 여러개면 ,로 쭉쭉 나열 가능
String [] configLocation=new String[] {"app2.xml"};
//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
AbstractApplicationContext context=
new ClassPathXmlApplicationContext(configLocation);
//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정
context.registerShutdownHook();
//4.xml에서 만들어진 객체를 가져와서 처리
//형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
SystemMoniter moniter=
context.getBean("moniter",SystemMoniter.class);
System.out.println("moniter=>"+moniter);
//5.context도 종료
context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
}
}
5. @Autowired을 메서드위가 아니라 멤버변수에 적용한다면?
SystemMoniter.java에서 Setter Method는 필요 없어지기에 지워주고 멤버변수 위에 @Autowired을 적용한다.
=> 이렇게 해도 객체를 얻어올수있어 결과는 같다
멤버변수에 적용하면 굳이 setter 메서드를 안만들어도되서 더 편리하다 그래서 주로 이렇게 변수위에 만든다.
package anno2;
//문자를 전송=>기간을 정하기
public class SystemMoniter {
private long periodTime;//기간
//has a 관계 =>두 클래스가 연결
//@Autowired(required=false) //빈즈객체가 없어도 에러유발 X 있으면 넣어준다
@Autowired
private SmsSender sender;
//Setter Method
public void setPeriodTime(long periodTime) {
this.periodTime = periodTime;
System.out.println("setPeriodTime() call");
}
@Override
public String toString() {// Setter메서드로 잘 설정됐는지 확인할수있음
// TODO Auto-generated method stub
return "SystemMoniter[periodTime="+periodTime+",sender="+sender+"]";
}
}
6. @Autowired(required=false)옵션 추가 =>빈즈객체가 없어도 에러유발 X 있으면 넣어준다
@Inject
@Inject는 @Autowired와 비슷한 기능으로 더 최신버전이다.
따라서 위에 @Autowired의 예제에서 @Autowired를 @Inject로만 바꾼다.
@inject는 외부패키지라 pom.xml에 추가해줘야한다
<!-- @Inject 추가 -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
@Resource
@Resource 객체의 이름을 이용하여 의존성 주입을 처리한다
name속성을 사용할수있어서 해당 이름으로 생성된 객체를 검색하여 의존성 주입을 처리한다.
@Resource 을 사용하기위해서 pom.xml에 소스를 넣어야한다.
@Resource와 @Autowired 의 공통점과 차이점
공통점:자동으로 객체를 찾아서 넣어준다.
차이점: byName vs byType
@Resource - byName(이름으로 찾아서 자동으로 객체를 넣어주는 개념)
같은 클래스 자료형이 여러개있을때 어떻게 구분?-> 이름으로 구분
@Autowired - byType(같은 자료형을 찾아서 자동으로 객체를 넣어주는개념)
@Resource 을 사용하기위해서 pom.xml에 소스를 넣어야한다.
<!-- @Resource -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
1. Camera.java 생성
package anno3;
import org.springframework.beans.factory.annotation.Required;
public class Camera extends Object{// 모든객체는 extends Object를 생략하고있다
private int number;//카메라수 0
@Required
public void setNumber(int number) {
this.number = number;
System.out.println("setNumber() call");
}
//메서드이름 위에 기술=>메서드명이 오버라이딩이 된 메서드인지 확인해주는 기능을 가진 어노테이션
@Override
public String toString() {
// TODO Auto-generated method stub
return "Camera[number="+number+"]";
}
}
package anno3;
import javax.annotation.Resource;
public class HomeController {
@Resource(name="camera2")//=> <bean id="camera2" class~
private Camera camera2; // 멤버변수에 @Resource 적용
private Camera camera3;
private Camera camera4;
// Setter Method에 @Resource 적용
@Resource(name="camera3") //id가 camera3인 클래스객체를찾아서 저장
public void setCamera3(Camera camera3) {
this.camera3 = camera3;
System.out.println("setCamera3() call");
}
@Resource(name="camera4") //id가 camera4인 클래스객체를찾아서 저장
public void setCamera4(Camera camera4) {
this.camera4 = camera4;
System.out.println("setCamera4() call");
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "HomeController[camera2="+camera2+",camera3="+camera3+",camera4="+camera4+"]";
}
}
멤버변수에 @Resource을 적용하면 Setter 메서드는 지워도된다.
3. app2.xml 내용추가
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean id="camera2" class="anno3.Camera" p:number="2" />
<bean id="camera3" class="anno3.Camera" p:number="3" />
<bean id="camera4" class="anno3.Camera" p:number="4" />
<!-- has a 관계 -->
<bean id="homeController" class="anno3.HomeController" />
4. Main 생성
package anno3;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여 // xml이 여러개면 ,로 쭉쭉 나열 가능
String [] configLocation=new String[] {"app2.xml"};
//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
AbstractApplicationContext context=
new ClassPathXmlApplicationContext(configLocation);
//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정
context.registerShutdownHook();
//4.xml에서 만들어진 객체를 가져와서 처리
//형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
HomeController home=
context.getBean("homeController",HomeController.class);
System.out.println("home=>"+home);
//5.context도 종료
context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
}
}
@PostConstruct, @PreDestroy
@PostConstruct와 @PreDestroy는 간단히 개념설명만 하고자 한다.
@PostConstruct=빈즈객체 생성전에 초기화작업을 하고자할때(=생성자)사용
=>물건사기전에 돈을 선불로 지불하는것 가트이 먼저 초기화 작업
@PreDestroy=객체가 생성된 후에 작업->메모리 작업
=>물건을 먼저받고 나중에 후불로 돈지불하는것 처럼 나중에 작업
@Component
Camera 메서드를 빈즈를 생성하려면
< bean id="camera" class="anno5.Camera" /> 이런식으로 수동으로 작성한다
하지만 만약 이런게 30개가있다면? 수동으로 일일이 하긴 힘들다.
따라서 이럴때 자동으로 만들어줄때 사용하는 어노테이션이 @Component이다.
그동안 배운 어노테이션들을 일일이 설정하지 않고 @Component 하나로 적용할수있다
@Component
클래스와 관련된 어노테이션으로 스프링컨테이너가 어느 특정패키지를 지정 하면 자동적으로 그 패키지에 들어가 있는 모든 클래스중에서 @Component가 붙어있는 클래스를 빈즈로 자동으로 등록한다.
1. 각각 다른클래스에 Camera.java, Camera2.java, Camera3.java를 생성
Camera.java
package anno5;
import org.springframework.stereotype.Component;
/*
*빈즈에 관련된 클래스가 30개 이상이라면
*
* <bean id="camera" class="anno5.Camera" /> =>수동으로 등록 /밑에 Camera를 빈즈로 생성 근데 이런게 30개가있다면? 수동으로 일일이 하긴 힘듬
* ,,,,
*
* @Component =>클래스와 관련된 어노테이션
* 스프링컨테이너가 어느 특정패키지를 지정 ->자동적으로 그 패키지에 들어가 있는
* 모든 클래스중에서 @Component가 붙어있는 클래스를 빈즈로 등록(자동)
*/
@Component
public class Camera{} //기본생성자 자동생성->호출
Camera2.java
package anno5;
import org.springframework.stereotype.Component;
@Component
public class Camera2{} //기본생성자 자동생성->호출
Camera3.java
package anno5;
import org.springframework.stereotype.Component;
@Component
public class Camera3{} //기본생성자 자동생성->호출
2. HomeController2 생성
package anno5;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class HomeController2 {
@Inject
private Camera camera;
@Autowired
private Camera camera2;
@Autowired
private Camera camera3;
// 위에 3개에는 어노테이션을 굳이 안해도됨 (@Component 을 적용했뗴문에)
@Override
public String toString() {
// TODO Auto-generated method stub
return "HomeController2[camera="+camera+",camera2="+camera2+",camera3="+camera3+"]";
}
}
클래스 위에 @Component 을 적용했기에 @Inject, @Autowired, @Autowired 이 세개는 굳이 안해도된다.
3. appScan.xml 생성
어노테이션 및 특정패키지에 들어가 있는 모든 클래스의 빈즈객체를 빈즈로 자동으로 등록(옵션)
이전에는 이렇게 수동으로 직접 4개를 등록했었다.
<bean id="homeController2" class="anno5.HomeController2" />
<bean id="camera" class="anno5.Camera" />
<bean id="camera2" class="anno5.Camera2" />
<bean id="camera3" class="anno5.Camera3" />
하지만 @Component을 적용하면 다음과 같이 간단히 가능하다.
<!-- @Component로 등록한 모든 객체를 자동으로 다 생성-->
<context:component-scan base-package="anno5" />
4. Main.java 생성
package anno5;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여 // xml이 여러개면 ,로 쭉쭉 나열 가능
String [] configLocation=new String[] {"appScan.xml"};
//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
AbstractApplicationContext context=
new ClassPathXmlApplicationContext(configLocation);
//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정
context.registerShutdownHook();
//4.xml에서 만들어진 객체를 가져와서 처리
//형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
HomeController2 home2=
context.getBean("home",HomeController2.class);
System.out.println("home2=>"+home2);
// id나 name을 xml에서 정하지 않았는데 되는 이유 => 자동으로 기본클래스이름 통해서 가져옴 (클래스이름에서 앞글자 소문자)
// 임의로 정해주고싶다면 @Conmponent("부여할 id이름지정")
//5.context도 종료
context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
}
}
@Component을 사용하면 간단히 가능하지만 굳이 여러 어노테이션들을 하나하나 배운 이유는 기초를 알아야 재대로 이해할수있기 때문이다.
@Transactional
sql구문들을 트랜잭션처리해주는 어노테이션
2022-08-23