www.youtube.com/watch?v=XtXHIDnzS9c&list=PLq8wAnVUcTFUHYMzoV2RoFoY2HDTKru3T
Java SE를 기반으로 하고
Java EE 에서 Spring 으로 사용하는 것으로 바뀌었다.
ClassA a = new ClassA();
a.doSomething();
위와 같은 코드는 B1, B2등의 클래스가 생겼을때 관계가 바뀔 때 마다 코드를 수정해야 한다.. 즉 유연하지 못하다.
예를 들면 아래와 같이 바꾸어야 한다.
ClassB1 b1 = new ClassB1();
b1.doSomething():
ClassB2 b2 = new ClassB2();
b2.doSomething():
이런 것은 Interface로 해결할 수 있다.
ClassesOfIF i = new ClassA();
i.doSomething();
하지만 여전히 new 선언 부분은 코드가 달라지는데..
이것은 XML, Annotaion 등으로 선언한 객체를 삽입받아 해결할 수 있다.
www.youtube.com/watch?v=YZzpGtpW2h0&list=PLq8wAnVUcTFV4ZjRbyGnw6T1tgmYDLM3P&index=88
아래와 같은 inerface를 상속하는 클래스 A, B 가 있다.
package mkobj;
public interface X {
int doCalc(int a, int b, int c);
}
public class A implements X {
@Override
public int doCalc(int a, int b, int c) {
return a+b+c;
}
}
public class B implements X {
@Override
public int doCalc(int a, int b, int c) {
return a*b*c;
}
}
Main클래스 내 main 함수
X x = new A();
int x1 = x.doCalc(1, 2, 4);
System.out.println("x1: " + x1);
x = new B();
int x2 = x.doCalc(1, 2, 4);
System.out.println("x2: " + x2);
결과:
x1: 7
x2: 8
위와 같이 실행되는데.. 이것을.. 따로 설정 파일을 때어내서 핸들링 할 수 있다.
setObj.txt 파일이다.
mkobj.B
그리고 아래는 수정한 main 함수이다.
FileInputStream fis = new FileInputStream("src/mkobj/setObj.txt");
Scanner scan = new Scanner(fis);
String str = scan.nextLine();
scan.close();
fis.close();
Class<X> clazz = (Class<X>) Class.forName(str);
X y = (X) clazz.newInstance();
int y1 = y.doCalc(1, 2, 4);
System.out.println("y1: " + y1);
결과는 setObj 파일을 A, B로 바꿈에 따라 바뀐다 !!!
DI
A객체 안에 안에 B 객체를 넣는 방법을 생각해 보자
하난 일체형
class A {
private B b;
public A() {
b = new B();
}
}
다른 하난 조립형이다.
class A {
private B b;
public void setB(B b) {
this.b = b;
}
}
조립형의 경우 Setter와 Construction 주입을 할 수 있다.
Setter와 Construction 방식이 있다.
DI는 사용자가 작성한 방식과는 반대되는 방향으로 일어나기 때문에
IoC라고도 표현 한다. Inversion of Control
그리고 생성된 객체들이 보관된, 담긴 곳은 IoC Container 라고 한다.
Spring Bean Configuration 파일을 통해서 DI 지시서, 즉 DI 설정 xml파일을 만들 수 있다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<!-- Exam exam = new NewlecExam(); -->
<bean id="exam" class="newlecture_spring.di.entity.NewlecExam"/>
<!-- ExamConsole console = new InlineExamConsole(exam); -->
<bean id="console" class="newlecture_spring.di.ui.InlineExamConsole">
<!-- console.setExam(exam); -->
<property name="exam" ref="exam"/>
</bean>
</beans>
property의 name은 사실은 setExam 함수명의 이름이다. 변수명등이 아니다. 명사가 아닌 동사의 이름인 것이다.
value와 ref의 속성이 있는데, value는 primitive Type이고, ref는 referrence 이다.
Maven Repository: Search/Browse/Explore (mvnrepository.com)
SpringFramework 검색 후 Spring Context를 메이븐 설정에 추가 해주자.
ApplicationContext context = new ClassPathXmlApplicationContext("newlecture_spring/di/setting.xml");
//ExamConsole console = (ExamConsole) context.getBean("console");
ExamConsole console = context.getBean(ExamConsole.class);
문자열로 꺼낼 수 있고
Class 형식으로 꺼낼 수 있는데,
Class로 꺼내는 것이, 형변환도 안해도 되고 명확히 인자로 전달 할 수 있기 때문에 더 선호 된다.
<bean id="exam" class="newlecture_spring.di.entity.NewlecExam">
<property name="kor" value="50" />
<property name="eng" value="80" />
<property name="math" value="100" />
<property name="com" value="90" />
</bean>
위와 같이 property로 값을 부여할 수 있다 . (setter Injection)
혹은
<bean id="exam" class="newlecture_spring.di.entity.NewlecExam" >
<constructor-arg name="kor" value="30" />
<constructor-arg name="eng" value="50" />
<constructor-arg name="com" value="70" />
<constructor-arg name="math" value="90" />
</bean>
위와같이 contstructor로도 가능하며, name대신에 index로도 설정 가능하고 type을 줄수도 있다.
혹은 위와 같이 NameSpaces 탭을 통해서 p 태그를 추가하면,
<bean id="exam" class="newlecture_spring.di.entity.NewlecExam" p:kor="50" p:math="90" />
이렇게도 설정 가능하다.
Collection 중에서 list를 한번 추가해 보자.
List<Exam> exams = new ArrayList<>();
List<Exam> subList = new ArrayList<>();
subList.add(new NewlecExam(1, 1, 1, 1));
subList.add(new NewlecExam(1, 1, 1, 2));
List<Exam> exams = new ArrayList<>(subList);
위 선언문은 아래와 같이 작성될 수 있다.
<bean id="exams" class="java.util.ArrayList">
<constructor-arg>
<list>
<bean id="exam" class="newlecture_spring.di.entity.NewlecExam" >
...
</bean>
<ref bean="exam" />
</list>
</constructor-arg>
</bean>
혹은 util을 이용할 수 있다.
<util:list list-class="java.util.ArrayList" id="exams">
...
</util:list>
XML -> @(Annotaion)
XML 외부문서에서 내부 자바코드로 바꾸어 보자.
NamSpace를 추가한 후에 아래 태그를 setting.xml에 설정한다 !
<context:annotation-config />
위 설정은 XML에 선언된 객체 내부에 Annotaion 설정 정보를 살펴보라는 얘기이다. 없으면 살피지 않는다.
<bean id="console" .. >
<!-- <property name="exam" ref="exam"/> -->
</bean>
그 후에 property를 주석처리 한후에
위와 같이 setter에 @Autowired해 주면.. 주입이 일어난다 !!
그런데 이 DI Injection을 무엇을 기준으로 주입하냐면 보통 1차로 자료형을 기준으로 2차로는 이름을 기준으로 본다.
xml설정에 알맞은 자료형이 있으면 찾아서 넣어준다.
문제는 해당 자료형이 2개 있는 경우인데
<bean class="newlecture_spring.di.entity.NewlecExam" >
<bean class="newlecture_spring.di.entity.NewlecExam" >
그러면 위와 같은 에러가 발생한다.
이때 bean에 id를 부여해 setter의 이름을 맞추어주면, 둘 중에 하나를 가려낸다.
아니면 특정 id에 대해 주입받고자 한다면 아래와 같이 주입도 간으하다.
<bean id="examCute" class="newlecture_spring.di.entity.NewlecExam" >
<bean class="newlecture_spring.di.entity.NewlecExam" >
Qualifier는.. Constructor의 경우 아래와 같이 설정할 수 잇다.
@Autowired(required = false)
false로 설정하면, DI받으려는 객체가 null 이어도 허용한다.
자 이제 스프링이 관리하는 bean 객체 내부의 객체를 DI하는 방법을 알아보았으니,
XML에 있는 bean을 애노뗴이숀으로 뺴구 bean으로 등록하는 방법을 알아보자.
<context:annotation-config />
위 설정은 bean에 등록된 객체 내부에 Annotaion 을 살펴보라는 뜻인데,
bean으로 등록돼 있지 않으면 살펴 보지 않는다.
base-package="newlecture_spring.di.ui, newlecture_spring.di.entity"
경로는 위와 같이 2개 이상을 설정할 수도 있으며,
newlecture_spring.di 를 넣으면 .ui 와 .entity를 포괄하는 상위 패키지가 지정된다.
강의 실습을 하던 도 중
Error creating bean with name 'exam' defined in file
라는 오류 메시지가 떴었는데 이는 인자를 받는 생성자(Overloaded Constructor)는 있으나 기본 생성자가 없어서 생긴 오류였다.
다시 말하면 Exam(Parameter p1 ...) 은 있지만 Exam() 은 없었기 때문에 스프링이 생성하지 못한 것이다.
@Value("20")
private int kor;
값은 위와 같이 설정 가능하다.
Java Configuration
ComponentScan에 2개 이상의 인자를 넣을 때는
@ComponentScan ({spring.di.ui, spring.di.entity})
라고 넣으면 된다.
main함수에는 위와같은 코드를 넣어주자.
public class NewlectAppConfig {
@Bean
public Exam exam() {
return new NewlecExam();
}
@Bean
public ExamConsole console() {
return new InlineExamConsole();
}
}
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(NewlectAppConfig.class);
ExamConsole console = (ExamConsole) context.getBean("console");
console.print();
}
위와 같은 설정이 Java 설정이다 !!
'Back-end > Spring Boot, JPA' 카테고리의 다른 글
newlecture: spring MVC 1 (0) | 2021.04.26 |
---|---|
newlecture: spring AOP (ft.빵또아) (0) | 2021.04.24 |
스프링 활용 JPA 강의 내용 기록 (0) | 2021.03.29 |
스프링 intro 강의 복습 차원 정리, ★ 단축키 (0) | 2021.03.19 |
기타 오류들 해결... (lombok 설정 등) (0) | 2021.03.07 |
hi hello... World >< 가장 아름다운 하나의 해답이 존재한다
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!