의존성 주입
개발자가 아닌 컨테이너가 컴포넌트(클래스) 연관 관계 규정
약한 결합(loosely coupled), 의존 관계 최소화
다른 클래스의 변경 사항에 영향을 받지 않음 -> 자유로운 클래스 변경 가능
코드 단순화
쉬운 유지 관리
제어 역행(역전)
개발자가 아닌 스프링에서 직접 객체를 제어
스프링에서는 DI로 IoC를 구현
class Controller, class Service, class DAO
BoardService.java
public class BoardService {
BoardDAO boardDAO;
public BoardService() {
boardDAO = new BoardDAO(); //직접 생성
}
...
interface Controller, interface Service, interface DAO,
class ControllerImpl implements Controller,
class ServiceImpl implements Service,
class DAOImpl implements DAO
기능 변경 시 인터페이스를 구현한 새로운 클래스를 작성하여 사용
BoardServiceImpl.java
public class BoardServiceImpl implements BoardService{
private BoardDAO boardDAO;
/* 생성자 이용 방식 */
public BoardServiceImpl(BoardDAO boardDAO){
this.boardDAO = boardDAO; //주입된 객체 사용
}
/* setter 이용 방식 */
public void setBoardDAO(BoardDAO boardDAO){
this.boardDAO = boardDAO; //주입된 객체 사용
}
...
<bean> 태그XML 파일에서 DI 설정 시 사용하는 태그
id: bean 객체 고유 이름, 접근 이름
name: 객체 별칭
class: 패키지.생성할 클래스
constructor-arg: 생성자 방식
property: setter 방식
pro19/person.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="personService1" class="com.spring.ex02.PersonServiceImpl">
<constructor-arg value="이순신" />
</bean>
<bean id="personService2" class="com.spring.ex02.PersonServiceImpl">
<constructor-arg value="손흥민" />
<constructor-arg value="23" />
</bean>
</beans>
pro19/com.spring/ex02/PersonServiceImpl.java
package com.spring.ex02;
public class PersonServiceImpl implements PersonService {
private String name;
private int age;
public PersonServiceImpl(String name) {
this.name = name;
}
public PersonServiceImpl(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public void sayHello() {
System.out.println("이름: " + name);
System.out.println("나이: " + age + "살");
}
}
pro19/com.spring/ex02/PersonTest.java
package com.spring.ex02;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class PersonTest {
public static void main(String[] args) {
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("person.xml"));
PersonService person1 = (PersonService) factory.getBean("personService1");
person1.sayHello();
System.out.println();
PersonService person2 = (PersonService) factory.getBean("personService2");
person2.sayHello();
}
}
pro19/person.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="personService" class="com.spring.ex01.PersonServiceImpl">
<property name="name">
<value>홍길동</value>
</property>
</bean>
</beans>
pro19/com.spring/ex01/PersonService.java
package com.spring.ex01;
public interface PersonService {
public void sayHello();
}
pro19/com.spring/ex01/PersonServiceImpl.java
package com.spring.ex01;
public class PersonServiceImpl implements PersonService {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
@Override
public void sayHello() {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
}
}
pro19/com.spring/ex01/PersonTest.java
package com.spring.ex01;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class PersonTest {
public static void main(String[] args) {
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("person.xml")); //xml을 통해 bean 생성
PersonService person = (PersonService) factory.getBean("personService"); //bean 가져오기
person.sayHello();
}
}
pro19/member.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="memberService" class="com.spring.ex03.MemberServiceImpl">
<property name="memberDAO" ref="memberDAO" />
</bean>
<bean id="memberDAO" class="com.spring.ex03.MemberDAOImpl" />
</beans>
pro19/com/spring/ex03/MemberServiceImpl.java
package com.spring.ex03;
public class MemberServiceImpl implements MemberService {
private MemberDAO memberDAO;
public void setMemberDAO(MemberDAO memberDAO) {
this.memberDAO = memberDAO;
}
@Override
public void listMembers() {
memberDAO.listMembers();
}
}
pro19/com/spring/ex03/MemberDAOImpl.java
package com.spring.ex03;
public class MemberDAOImpl implements MemberDAO {
@Override
public void listMembers() {
System.out.println("listMembers 메서드 호출");
System.out.println("회원정보를 조회합니다.");
}
}
pro19/com/spring/ex03/MemberTest1.java
package com.spring.ex03;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class MemberTest01 {
public static void main(String[] args) {
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("member.xml"));
MemberService service = (MemberService) factory.getBean("memberService");
service.listMembers();
}
}
관점 지향 프로그래밍 Aspect Oriented Programming
메소드 안의 보조기능들을 분리하여 선택적으로 사용
aspect: 보조기능
advice: aspect 구현체 (클래스)
advisor: advice+pointcut 결합
joinpoint: advice 적용 지점
pointcut: advice 적용 대상 정규식 (패키지명/클래스명/메소드명)
target: advice 적용 클래스
weaving: advice를 주기능에 적용
AOP 수행 시점
void before(Method method, Object[] args, Object target) throws Throwablevoid afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwablevoid afterThrowing(Method method, Object[] args, Object target, Exception ex)Object invoke(MethodInvocation invocation) throws Throwablepro20/src/AOPTest.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="calcTarget" class="com.spring.ex01.Calculator" /> <!-- target -->
<bean id="logAdvice" class="com.spring.ex01.LoggingAdvice" /> <!-- advice -->
<bean id="proxyCal" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- target + advice -->
<property name="target" ref="calcTarget"/>
<property name="interceptorNames">
<list>
<value>logAdvice</value> <!-- 메소드 호출 시 실행 -->
</list>
</property>
</bean>
</beans>
pro20/src/com.spring/ex01/Calculator.java
target 클래스
package com.spring.ex01;
public class Calculator {
public void add(int x, int y) {
int result = x + y;
System.out.println("결과:" + result);
}
public void subtract(int x, int y) {
int result = x - y;
System.out.println("결과:" + result);
}
public void multiply(int x, int y) {
int result = x * y;
System.out.println("결과:" + result);
}
public void divide(int x, int y) {
int result = x / y;
System.out.println("결과:" + result);
}
}
pro20/src/com.spring/ex01/LoggingAdvice.java
advice 클래스
package com.spring.ex01;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class LoggingAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("[메서드 호출 전 : LogginAdvice");
System.out.println(invocation.getMethod() + "메서드 호출 전");
Object object = invocation.proceed();
System.out.println("[메서드 호출 후 : loggingAdvice");
System.out.println(invocation.getMethod() + "메서드 호출 후");
return object;
}
}
pro20/src/com.spring/ex01/CalcTest.java
package com.spring.ex01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CalcTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("AOPTest.xml");
Calculator cal = (Calculator) context.getBean("proxyCal");
/* 메소드 호출 - 호출 전후로 advice bean 적용 */
cal.add(100, 20); System.out.println();
cal.subtract(100, 20); System.out.println();
cal.multiply(100, 20); System.out.println();
cal.divide(100, 20);
}
}
출력 결과
advice 출력 내용 (메소드 호출 전)
target 출력 내용 (메소드)
advice 출력 내용 (메소드 호출 후)
*자바 웹을 다루는 기술