Spring에서 지원하는 ServletContextAware를 구현(implements)하면 거의 거져 먹여주는 꼴이다.

 

@Controller
public class TestController implements ServletContextAware{
	@Override
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}
}

 

'프로그래밍 > Spring' 카테고리의 다른 글

Spring | collection & association  (0) 2020.12.24
Spring | AOP  (0) 2020.12.23
Spring - DI  (0) 2020.12.22

 

위의 emp는 dept의 deptno를 외래키로 참조하는 테이블이다.

내부조인 : select * from dept left outer emp e join on d.deptno = e.deptno;

외부조인 : select * from dept d left outer join emp e on d.deptno = e.deptno;

와 같이 SQL쿼리를 사용하여 조인할 수 있다. 

 

이렇게 값을 얻어서 VO에 넣어서 저장하기가 애매(?)할 수가 있다.

 

Mybatis를 이용하여 조인을 처리하여 VO의 저장할 수 있는 방법이 있다.

 

collection1:多관계에서 쓰이는 방법으로 부모의 레코드를 뽑아내면서 해당 레코드를 참조하는 자식의 레코드들을 뽑아낼 수 있다. -> 어떻게보면 이중포문과 비슷하다고 생각이 들 수 있다.

 

사용하게되는 태그 resultMap과 select면 된다.

resultMap은 select태그의 속성 중 resultMap이라는 속성이 존재한다.

resultMap을 먼저 선언한 뒤, select에서 참조하는 방법이다.

<!-- 조인 시 VO가 두개의 컬럼을 감당할 수 있어야함...  -->
	<!-- 쿼리결과와 객체간 매핑을 자동으로 하는 것이 아니라, 
	개발자가 주도하여 처리를 하고 싶을때는 별도의 매핑을 선언.. -->
	<!-- 매핑의 커스터마이징 -->
	<resultMap type="Dept" id="deptJoinEmp">
	<!-- column=query에서 뽑아진 컬럼명 -->
		<id column="deptno" property="deptno"/><!-- primary key -->
		<result column="dname" property="dname"/><!-- 일반컬럼 -->
		<result column="loc" property="loc"/>
		<!-- 부서정보가져오고 부서정보에 포함되는 외부에 있는 부서원정보가져오기-->
		<!-- Emp(ofType)로 구성된  List(javaType)-->
		<!-- deptno컬럼을 가져오겠다. -->
		<!-- propery는 set메서드를 생각 -->
		<collection column="deptno" javaType="java.util.List" ofType="Emp" select="Emp.select"  property="empList"/>
	</resultMap>
	<!-- 이중포문과 비슷 dept정보를 가져올 때 그 정보를 가지고 emp정보를 가져오고 다음 dept가져오면 그 dept에 대한 emp를 뽑아온다. -->
	<select id="selectAll" resultMap="deptJoinEmp">
		select deptno, dname, loc from dept 
	</select>
	

resultMap은 매핑을 개발자가 커스터마이징하여 내가 만든 VO에 맞게 조인할 수 있다.

resultMap태그의 속성 중 type은 만들 VO객체를 말하고 id는 select에서 참조할 수 있게 이름을 지어주는 것이다.

id는 테이블의 primary key를 매핑하는 것이고, result는 일반 컬럼들을 매핑하는 것이다.

위 태그의 속성 중 column은 쿼리로 뽑아배는 레코드의 컬럼을 말하고, property는 VO객체의 set메서드를 말한다.

collection의 속성 중 javaType은 만들 자료형을 말하고 ofType은 javaType이 List와 같은 제네릭형일 때 자료형을 정해준다. select는 자식의 Mapper에서의 사용할 쿼리id를 말한다.

 

<resultMap id="empJoinDept" type="Emp" >
		<id column="empno" property="empno"/><!-- primary key -->
		<result column="ename" property="ename"/>
		<result column="job" property="job"/>
		<result column="mgr" property="mgr"/>
		<result column="hiredate" property="hiredate"/>
		<result column="sal" property="sal"/>
		<result column="comm" property="comm"/>
		<!-- 자식관점에서는 부모와 1:1 관계로 가져옴 -->
		<association column="deptno" property="dept" javaType="Dept" select="Dept.selectById"/>
	</resultMap>
	
	<!-- 사원테이블 정보 가져오기 -->
	<select id="selectAll" resultMap="empJoinDept">
		select * from emp
	</select>

association1:1관계에서 사용할 수 있는 조인이다. 즉, 자식이 참조하고 있는 컬럼에 대한 부모레코드를 참조할 수 있다.

위 collection 이해할 수 있다면 association을 쉽게 이해할 수 있다.

'프로그래밍 > Spring' 카테고리의 다른 글

Spring - ServletContext 쉽게 가져오기  (0) 2021.01.05
Spring | AOP  (0) 2020.12.23
Spring - DI  (0) 2020.12.22

DI를 사용할 경우 클래스내의 멤버변수에 대한 의존도가 낮아지게 되면서 결합도가 낮아진다.

하지만, 멤버변수의 존재가 아예 사라진다는 경우에 과연 결합도가 없다고 할 수 있을까?

 

이를 해결하기위해 Spring에서는 AOP를 사용하였다.

 

AOP란?

클래스내의 멤버변수와의 의존도를 아예 없게 함으로써 다른 클래스와의 결합도를 낮추는 기법이다.

Spring은 AspectJ의 기술을 채용하여 사용하였다.  

 

쓰는 이유?

예로 쇼핑몰 웹사이트를 제작 시 장바구니, 구매 등등 로그인 상태를 체크를 반드시 필요로 하는 페이지가 존재한다.

이런 경우 AOP와 같은 기술을 사용하지 않게 되면 해당 페이지의 컨트롤러와 같은 클래스나 페이지내에서 의존하게 된다. 이를 AOP와 같은 기술을 사용하여 분리하게 되면 프로그램의 유지보수가 상당히 편할 것이다.

 

사용방법

mvnrepository의 Spring MVC를 가져와서 pom.xml에 추가해준다.

 

Spring에서 사용되는 jar들이 많이 생기는데 여기에서 AOP도 추가된다.

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.3.30.RELEASE</version>
		</dependency>

그리고 aspectJ에서 지원하는 weaber 또한 필요로 한다.

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.14</version>
			<scope>runtime</scope>
		</dependency>

 

아래의 코드로 예를 들어본다면, Student클래스내에 각 메서드들의 실행 시작과 실행 후에 Bell클래스의 메서드인 startBell(), endBell()실행하도록 만들어봄으로써 AOP를 이해할 수 있다.

package test;

public class Student {
	
	public void study1() { //영어시간
//		System.out.println("♬ 시작 종"); //종이 울리는 것은 학생과 관련된 기능이 아님!!! 그리고 중복된다.
		System.out.println("1교시는 영어시간이에요");
	}
	public void study2() {//국어시간
		System.out.println("2교시는 영어시간이에요");	
	}
	public void study3() {//물리시간
		System.out.println("3교시는 물리시간이에요");	
	}
	public void study4() {//수학시간
		System.out.println("4교시는 수학시간이에요");
	}
}
package test;

public class Bell {
	public void startBell() {
		System.out.println("♬ 시작 종");
	}
	
	public void endBell() {
		System.out.println("♬ 종료 종");
	}
}

 

<!-- 학생과 벨을 엮어보자(weaving) -->
	
	<!-- AOP를 이용하기 위해서는, 공통로직 즉 횡단적 관심사항을 등록한다!! -->
	<bean id="bell" class="test.Bell"/>
	
	<!-- 어떤 시점에, 어떤 객체에게 횡단점 관심사항을 적용할지 xml태그로 서술한다..
		즉 프로그램 코드가 아닌 xml과 같은 설정파일에서 구현하는 방법을 선언적이라한다.. 
	-->
	<aop:config>
		<aop:aspect id="bellAspect" ref="bell">
			<!-- 어떤 시점에 벨이 관여할지를 결정 -->
			<!-- test..*(..) 테스트 패키지 아래의 모든 클래스의 모든 메서드 -->
			<aop:pointcut expression="execution(public * test.Student.*(..))" id="bellpointcut"/>
			<aop:pointcut expression="execution(public * test.Dog.*(..))" id="pointcutToDog"/>
			<!-- 공통기능 동작을 언제 할지, 즉 학생의 동작 이전에 적용, 이후에 동작시킬지.. -->
			<aop:before method="startBell" pointcut-ref="bellpointcut"/>
			<aop:after method="endBell" pointcut-ref="bellpointcut"/>
			<aop:before method="startBell" pointcut-ref="pointcutToDog"/>
			<aop:after method="endBell" pointcut-ref="pointcutToDog"/>
		</aop:aspect>
	</aop:config>
	<bean id="student" class="test.Student"/>
	<bean id="dog" class="test.Dog"/>

Bell클래스의 인스턴스가 Student의 메서드들의 실행을 관찰하고 있다고 생각하면 쉬운 것 같다.

'프로그래밍 > Spring' 카테고리의 다른 글

Spring - ServletContext 쉽게 가져오기  (0) 2021.01.05
Spring | collection & association  (0) 2020.12.24
Spring - DI  (0) 2020.12.22

DI(Dependency Injection)란?

직역하면 "의존성 주입"이라는 표현을 할 수 있지만, 이는 개념을 이해하기에 좋지 못한 표현이다. Spring에서 사용하는 뜻에 맞게 의역하면 "의존성있는 객체는 외부에서 주입하는 것"이라고 표현할 수 있다.

 

public class FryPan{
	public void boil(){
    	System.out.println("불을 이용해 요리합니다.");
    }
}
public class Cook{
	FryPan fryPan;
    public void init(){
    	fryPan = new FryPane();
    }
    
    public static void main(String[]agrs){
    	fryPan.boid();
    }
}

예를 들어 위와 같은 코드보면, Cook클래스은 FryPan클래스의 의존하고 있는 상태이다. 

위와 같이 의존성이 강한 상태에서 fryPan의 인스턴스를 생성하기 위해서 new연산자를 이용할 수 밖에 없다.

이는 FryPan을 다른 클래스로 바꿔야한다는 상황이 올 때 직접 Cook코드를 열어 바꿔줘야한다.

-> 코드가 길어지고 복잡해지면 유지보수가 까다롭다.

public inteface Pan{
	public void boil();
}
public class FryPan implements Pan{
	@Override
    public void boil(){
    	System.out.println("불로 요리를 합니다");
    }
}
public class Cook{
	Pan pan;
	
    public void setPan(Pan pan){
    	this.pan = pan;
    }
    
    public static void main(String[]agrs){
    	fryPan.boid();
    }
}

위와 같이 인터페이스를 이용하여 코드의 결합도를 낮춰주고 좀더 유연하게 할 수 있다.

 

그리고 여기서 Spring은 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">

	<!-- 앞으로, 소스코드에서 new하지말고, 이 xml설정파일에서 사용할 객체를 명시하면 된다... 
		, 스프링의 ApplicationContext가 알아서 메모리에 인스턴스를 생성하고, 주입까지 해준다!!
		단, 주입받으려는 객체는 setter나 생성자가 명시되어 있어야  스프링이 주입을 할 수 있다.-->
	
	<!-- 프라이팬을 선언 -->
	<!-- 하나의 컴포넌트 = bean -->
	<bean id="friPan" class="food.FriPan"/>	
	<bean id="cook" class="food.Cook">
		<!-- cook내의 pan을 주입  
			cook내의 setter메서드 호출-->
		<property name="pan" ref="friPan"/>
	</bean>
</beans>
package food;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UseCook {
	public static void main(String[] args) {

		/*DI (Dependency Injection) 
		 : 직역 시, 의존성 주입..
		의역 시, 의존성있는 객체는 외부에서 주입받자!!!!
		 */		
			
		//스프링을 이용하지 않고 구현한 예
		//팬을 올리자
		/*
		 * FriPan pan = new FriPan(); Cook cook = new Cook();
		 * 
		 * cook.setPan(pan);//팬을 요리사에게 주입시키자!!
		 * 
		 * cook.makeFood();
		 */
		
		//스프링을 이용해서 객체를 주입시켜본다..
		//xml에 원하는 객체를 명시하면, 이 객체가 작성된 xml을 파악하여
		//객체들의 인스턴스를 생성관리해준다.. 이러한 역할을 수행하는 객체를 가리켜
		//Spring Context 객체라 한다!!!!! (외부파일을 통해 인스턴스 관리)
		ClassPathXmlApplicationContext context = null; //스프링xml 설정파일을 읽어서 작성된
		//객체의 인스터는스를 생성 및 관리해준다(주입도 해줌)
		//외부조립자(Assembler)
		context = new ClassPathXmlApplicationContext("spring/config/context.xml");
		
		//xml이 이미 읽혀진 상태이므로, 메모리에는 인스턴스들이 존재할 것이고, 그 중 어떤 인스턴스를 가져올지는
		//getBean메서드로 가져오면 된다..
		Cook cook = (Cook)context.getBean("cook");
		cook.makeFood();
	}
}

 

ClassPathXmlApplication객체를 이용하여 인스턴스를 생성할 xml을 지정하여 사용할 수 있다.

 

스프링을 사용하면 외부파일인 XML로 코드를 유지보수할 수 있고 코드의 결합도를 낮출 수 있다!

'프로그래밍 > Spring' 카테고리의 다른 글

Spring - ServletContext 쉽게 가져오기  (0) 2021.01.05
Spring | collection & association  (0) 2020.12.24
Spring | AOP  (0) 2020.12.23

+ Recent posts