열심히 끝까지
디바이스 융합 자바(Java) day64(2) - Spring (IoC[제어의 역행], AOP[관점지향 프로그래밍]) 본문
디바이스 융합 자바(Java) day64(2) - Spring (IoC[제어의 역행], AOP[관점지향 프로그래밍])
노유림 2022. 9. 13. 17:34[ 프레임워크 ]
개발을 어떻게 해야하는지 아웃라인을 제공
> Spring 프레임워크
a) 프레임워크를 사용하기 때문에 개발시간 단축
b) 관리가 용이 == 유지보수 용이
c) ★ 개발자들의 실력이 상향 평준화
d) "IoC와 AOP를 지원하는 경량의 프레임워크"
IoC 제어의 역행 -> 낮은 결합도
AOP 관점지향 프로그래밍 -> 높은 응집도
경량 -> 원래는 .jsp .servlet
[ IoC - 제어의 역행 ]
Inversion of Control
설명 -> ㅁㅁㅁㅁㅁㅁㅁㅁ -> 설명
insert.do 요청 -> new InsertAction() (=> FC에서 작성됨)
new InsertAction(req, res);
>> 유지보수 불리...
>> 이 문제를 container에게 맡김
>> 컨테이너에게 객체화를 담당시키자!
-> 자바 코드로 new 하는 것이 아니라, 컨테이너가 객체화 처리
-> 소스 코드에 new가 없음 -> 결합도가 낮아짐 -> 유지보수 용이
소스코드에 new 가 있다 == 의존관계를 명시
>> new가 없어야 함!
1) web.xml 은 서블릿 컨테이너에게 설정을 알려주는 파일
2) 무슨 설정? 만들어야할 서블릿에 관련된 설정
뭘 만들까? 언제 호출할까?
3) new를 작성하지 않음! 근데 객체화가 되었다!!!!
=> 서블릿 컨테이너가 했다!!!!
4) 기본 생성자 필요
5) .xml --->> @
6) 스프링 프레임워크가 @을 적극 사용하는 프레임워크 임
동작순서
web.xml이 로딩
-> /test.do 요청
-> a.Test 클래스를 객체화, doGet()메서드 호출(서블릿 컨테이너)
-> 브라우저(사용자, client)에 실행 결과 출력됨
결합도가 높은 코드의 결합도를 낮춰보자!
1) 인터페이스
객체지향 - 다형성을 사용
"설계"
2) 디자인 패턴 : 팩토리(Factory) 패턴 - 사용하는 것이 Spring
"Client에서 직접적으로 new 소스코드 xxx"
Factory의 역할
: 요청에 맞는 객체를 반환해줌
>> run > run configurations > java Application > Arguments에서 program argument 바꾸어서 실행도 가능
- IoC와 관련된 설정을 알려준다고 가정
>> .xml 파일 만들기
> src/main/resource에 제작
> IoC와 관련된 설정을 applicationContext.xml로 작성
-> 스프링 설정 파일
<bean id="phone" class="test.IPhone" />
== test.IPhone phone = new test.IPhone();
- 동작 순서
1) 클라이언트가 컨테이너를 로딩(9번 라인)
2) 이 때, 스프링 설정 파일을 참고하여 로드
3) 스프링설정파일의 <bean>을 보고 객체화
== 즉시 로딩(pre-loading) 방식
4) "phone" 객체 요청 == Lookup 행위 진행
5) 요청한 객체 반환
>> 객체를 요청하는 행위를 "Lookup" 한다고 한다.
>> 9번 라인 시점에서 객체화 완료
> Lookup 하기
<bean 여부에 따라 S가 파일에 뜨면 무조건 작동>
init-method="initMethod"
>> 초기화 작업을 처리하는 메서드
destroy-method="destroyMethod"
>> 객체 메모리를 해제할 때 호출하는 메서드
lazy-init="false"
>> Default 값, 무조건 값을 출력
lazy-init="true"
>> 호출할 때만 생성시키는 메서드(한번 더 검색)
<과거 방법>
DeleteAction da = new DeleteAction();
da.execute();
DeleteAction da = new DeleteAction();
da.execute();
DeleteAction da = new DeleteAction();
da.execute();
<Spring 방법>
DeleteAction da = new DeleteAction();
da.execute();
da.execute();
da.execute();
> 즉,
DeleteAction da1 = new DeleteAction();
DeleteAction da2 = da1;
DeleteAction da3 = da2;
>> da1,2,3는 같은 주소를 가지고 있음 == 하나의 객체를 공유하고 있음
>> "싱글톤 패턴" 유지
: new를 작성하는 사람(컨테이너)이 책임지고 싱글톤 패턴을 유지해야 함!
>> <bean id="iphone" class="test.IPhone" lazy-init="true" scope="singleton"/>
: 컨테이너에게 싱글톤 패턴을 유지할 수 있도록 설정이 되어있음!!
- 의존 관계를 IoC하는 방법 == 의존성을 주입하는 방법
[1] 생성자 주입(인젝션)
<주입 전>
public void volumeUp() {
watch = new AppleWatch();
// 객체화를 할 수 밖에 없음
// 이 것을 IoC 지원을 받아 처리해보기
watch.volumeUp();
}
<주입 후>
public IPhone(AppleWatch watch) {
// 미리 선언해주면 객체화 안해줘도 괜찮음
System.out.println("아이폰 객체 생성완료22");
this.watch=watch;
}
public void volumeUp() {
watch.volumeUp();
}
<bean id="iphone" class="test.IPhone">
<!-- 인자를 알아서 맞춰줌 -->
<constructor-arg ref="aw"/>
</bean>
<bean id="aw" class="test.AppleWatch"/>
<전체 코드>
- client.java
package test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Client {
public static void main(String[] args) {
// Spring 컨테이너를 동작시킬 수 있도록 코드 작성
AbstractApplicationContext factory=new GenericXmlApplicationContext("applicationContext.xml");
// Spring 컨테이너야, 나 폰 객체가 필요해(아이폰 객체 가지고 싶어..)!
// 형변환 필요
Phone phone=(Phone)factory.getBean("iphone");
phone.powerOn();
phone.volumeUp();
phone.volumeDown();
phone.powerOff();
factory.close();
/*
BeanFactory bf = new BeanFactory();
Phone phone = (Phone)bf.getBean("galaxy");
phone.powerOn();
phone.volumeUp();
phone.volumeDown();
phone.powerOff();
*/
}
}
- IPhone.java
package test;
public class IPhone implements Phone{
private AppleWatch watch;
// 애플워치로 소리를 업,다운 한다고 가정
private int battery;
public IPhone() {
System.out.println("아이폰 객체생성완료");
}
public IPhone(AppleWatch watch) {
// 미리 선언해주면 객체화 안해줘도 괜찮음
System.out.println("아이폰 객체 생성완료22");
this.watch=watch;
}
public IPhone(AppleWatch watch, int battery) {
System.out.println("아이폰 객체 생성완료333");
this.battery=battery;
System.out.println("아이폰 전원 On : " + battery);
this.watch=watch;
}
public void powerOn() {
System.out.println("아이폰 전원 ON");
}
public void powerOff() {
System.out.println("아이폰 전원 OFF");
}
public void volumeUp() {
// System.out.println("아이폰 소리++");
// watch = new AppleWatch();
// 객체화를 할 수 밖에 없음
// 이 것을 IoC 지원을 받아 처리해보기
watch.volumeUp();
}
public void volumeDown() {
// System.out.println("아이폰 소리--");
// watch = new AppleWatch();
// 객체화를 할 수 밖에 없음
watch.volumeDown();
}
}
- Galaxy.java
package test;
public class Galaxy implements Phone{
public void initMethod() {
System.out.println("객체를 초기화하는 작업을 처리하는 메서드...");
// bean할 때 불러오는 것 가능
}
public void destroyMethod() {
System.out.println("객체 메모리를 해제할 때 호출하는 메서드...");
// bean할 때 불러오는 것 가능
}
// @Override 진행된 것
public void powerOn() {
System.out.println("갤럭시 전원 ON");
}
public void powerOff() {
System.out.println("갤럭시 전원 OFF");
}
public void volumeUp() {
System.out.println("갤럭시 소리++");
}
public void volumeDown() {
System.out.println("갤럭시 소리--");
}
}
- Phone.java
package test;
public interface Phone {
public void powerOn();
public void powerOff();
public void volumeUp();
public void volumeDown();
}
- BeanFactory.java
package test;
public class BeanFactory {
// 이름을 들으면 객체를 반환
public Object getBean(String beanName) {
if(beanName.equals("galaxy")) {
return new Galaxy();
}
else if(beanName.equals("iphone")) {
return new IPhone();
}
return null;
}
}
- AppliactionContext.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">
<!-- IPhone을 설정하면 main/java의 IPhone에 s 불이 들어옴 -->
<!-- 소속 클래스로 변경 -->
<!-- test뒤에 IPhone을 Galaxy로도 변경 가능, 이 부분 덕분에 new 하지 않아도 결과 출력 -->
<bean id="phone" class="test.Galaxy" init-method="initMethod" destroy-method="destroyMethod"/>
<!-- 디폴트 설정으로 singleton이 들어감 -->
<!-- 여러개를 쓰는게 맞을 때, scope에 prototype으로 작성 -->
<!-- <bean id="iphone" class="test.IPhone" lazy-init="true" scope="singleton"/> -->
<!-- 생성자 인젝션 : 기존의 기본생성자를 쓰던 방법이 아니라서 tag로 인자를 알려주어야 함 + 객체 생성해야 함 -->
<!-- 컨테이너의 관리에 들어가게 됨 -->
<bean id="iphone" class="test.IPhone">
<!-- 인자를 알아서 맞춰줌 -->
<constructor-arg ref="aw"/>
<constructor-arg value="99"/>
</bean>
<bean id="aw" class="test.AppleWatch"/>
</beans>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[ AOP - 관점지향 프로그래밍 ]
: Aspect Oriented Programming
: 기존에 진행과정 코드를 뽑아내고 다음과 같이 남기는 것
진행 과정
DAO 핵심 로직(비즈니스 메서드, CRUD) + 횡단관심(공통 로직)(무조건 실행하는 로직)
(변경 전)
conn (횡)
pstmt (횡)
sql
rs
close (횡)
close (횡) -> JDBCUtil
↓
(변경 후)
.
.
sql
rs
.
.
각각의 로직에 맞는 코드 공간에 생기므로, 응집도가 높아짐 -> 유지보수 용이
'디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)' 카테고리의 다른 글
디바이스 융합 자바(Java) day65(2) - 스프링(@(어노테이션),컴포넌트(@Component),@Repository,@Service) (1) | 2022.09.14 |
---|---|
디바이스 융합 자바(Java) day65(1) - 스프링(생성자 인젝션(day64(2)참고), Setter 인젝션) (1) | 2022.09.14 |
디바이스 융합 자바(Java) day64(1) - Spring 설치 (0) | 2022.09.13 |
디바이스 융합 자바(Java) day55 - 이미지 미리보기 (0) | 2022.08.29 |
디바이스 융합 자바(Java) day54 - 이미지 업로드 (0) | 2022.08.26 |