Spring Framework ( 툴이 아닌 프레임워크)
이클립스도 프레임워크이다.
자바개발을 쉽게하자는 것 !!
함수( ) {
}
- 명령어들의 집합
- 중복을 제거하기위해서 함수를 잡는 것이다. ( 반복되는건 함수로 자른다 )
→ 실행속도는 느려진다. 갔다가 되돌아오므로
class 클래스 {
멤버함수
}
멤버함수는 클래스 안으로 들어가는 것
함수와 멤버함수는 똑같은 기능이다. 그냥 위치만 클래스 안으로 들어간 것
자바에서는 멤버함수를 메서드다 라고 부른다.
이름만 다르지 함수 멤버함수 메서드 3개 다 하는 역할을 똑같다.
라면이다라고 메뉴가 있으면 라면을 직접 끓여서먹을 수 있는 단계가 클래스 생성이라 하고
Test t = new Test( );
메모리에 Test라는 클래스 잡고 t라는 객체를 생성하는 것이다.
스프링에서도 클래스를 잡아준다.
~~~~.xml 안에서 생성을 한다. 태그 형식으로 생성을 한다.
<bean id="t" class="Test" />
xml로 인해서 안에 잡아서 생성을 하는 것
우리는 이걸 객체라고 부르지 않고 빈이라고 부르므로 빈 생성한다고 하는 것이다.
우리가 빈을 생성하는 방법에는 2가지를 저번시간에 배웠다.
1. <bean ~~> -- xml로 생성
2. @Component
3가지가 더 있다. 이제 배울 것이다 !!
이제는 new 하지말라는 것 !! 그렇다고 모든 클래스를 new하지 말라는 것은 아니다.
자바의 고정된 클래스는 빈으로 생성하지 않아도 된다. 빈으로 생성해도 되는데 굳이 빈으로 할 필요는 없다~
자주자주 변화하는 것은 생성, 소멸 라이프 사이클을 스프링으로 생성하는 것
누구의 상속을 받지 않는 POJO 형식으로 !!
우리는 지금 Maven만 사용한다. Gradle은 부트할 때 !!
우리가 스프링이라고 말하면 스프링 프레임워크를 말하는 것이다.
JDK 11, Tomcat 9.0, Spring 5.x 로 해야 잘 처리가 된다.
11로 설정을 해야하지만 프로젝트 만들 때는 버전을 바꿔도 상관이 없다.
Build Path로 해서 보면 17버전으로 잡아놓음 -- 한 번 더 확인만 해봄~!
context를 생성하는 방법에는 3가지 방법이 있다.
1. ApplicationContext context = new FileSystemXmlApplicationContext("src/applicationContext.xml");
2. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
2번이 조금 더 편하다. General로 생성하는 것도 있지만 그건 1번이랑 똑같으니 패스~
HelloSpring.java
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
//MessageBeanKo messageBeanKo = new MessageBeanKo(); //1대1, 결합도 100%
//MessageBean messageBean = new MessageBeanEn(); //부모 = 자식, 다형성, 결합도 낮추기
//스프링 설정 파일 이용
//ApplicationContext context = new FileSystemXmlApplicationContext("src/applicationContext.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MessageBean messageBean = (MessageBean) context.getBean("messageBean"); //applicationContext.xml에서 Bean의 id 값을 넣어주면 얻어온다는 것
messageBean.sayHello("Spring");
System.out.println();
MessageBean messageBean2 = (MessageBean) context.getBean("messageBean"); //applicationContext.xml에서 Bean의 id 값을 넣어주면 얻어온다는 것
messageBean2.sayHello("Spring");
System.out.println();
MessageBean messageBean3 = (MessageBean) context.getBean("messageBean"); //applicationContext.xml에서 Bean의 id 값을 넣어주면 얻어온다는 것
messageBean3.sayHello("Spring");
System.out.println();
}
}
결과는 똑같이 잘 나온다 !!
DI (Dependency Injection)
스프링의 핵심 개념
객체사이의 의존 관계를 자기 자신이 아닌 외부에 의해서 설정된다는 개념이다
스프링에서는 설정파일을 사용하여 손쉽게 객체간의 의존관계를 설정하기에
스프링을 DI컨테이너라고 부르기도 한다.
DI 컨테이너는 어떤 클래스가 필요로 하는 인스턴스를 자동으로 생성, 취득하여 연결시켜주는 역할을 한다.
DI 컨테이너가 인스턴스를 생성하도록 하려면 프로그램 소스 내부에서 new 로 직접 생성하지 않고
설정파일에서 필요로 하는 클래스의 정보를 설정해 주어야한다.
스프링은 각 클래스간의 의존관계를 관리하기 위한 방법
- Constructor Injection
- Setter Injection
class Test {
private String name;
}
private의 특징은 이 안에서만 접근가능 외부에서 접근 안 된다.
외부에서 접근해서 값을 넣어주고 싶을 때 생성자를 통해서 데이터를 전달한다.
생성자를 통하면 한 번만 데이터 값을 줄 수 있다.
처음에 한 번밖에 수행이 안되니까 수정을 원할 때는 setter을 이용하였다.
값을 가져올 때는 getter을 썼다.
스프링에서도 똑같아 DI로 의존하겠다.
- Constructor Injection -- 생성자 통해서
- Setter Injection -- setter통해서
개념 자체는 위에와 똑같이 들어간다.
1. Constructor Injection
: 생성자를 통해서 의존 관계를 연결시키는 것을 말한다.
: 생성자를 통해서 의존 관계를 연결하기 위해서는 XML 설정 파일에서
<bean>요소의 하위요소로 <constructor-arg>를 추가해야 한다.
① 전달인자가 2개 이상인 경우
기본데이터 타입일 경우에는 value 요소를 사용하여 의존관계를 연결시키기 위한 값을 지정
public class Foo {
public Foo(int a, String b) { }
}
[applicationContext.xml]
<bean id="foo" class="Foo">
<constructor-arg>
<value>25</value>
</constructor-arg>
<constructor-arg value="Hello" />
</bean>
앞에있는 것은 int 뒤에있는 것은 string
value 태그로 지정할 수 있고 / 속성으로 집어넣어도된다.
② index 속성을 이용하여 지정
[applicationContext.xml]
<bean id="foo" class="Foo">
<constructor-arg index="1" value="Hello" />
<constructor-arg index="0">
<value>25</value>
</constructor-arg>
</bean>
이렇게 인덱스로 지정하면 순서가 바뀌어도 된다.
③ type 속성을 이용하여 지정
[applicationContext.xml]
<bean id="foo" class="Foo">
<constructor-arg type="int" value="25" />
<constructor-arg type="java.lang.String" value="Hello" />
</bean>
④ 객체를 전달할 경우에는 ref 요소를 사용
public class Foo {
private Bar bar;
public Foo(Bar bar){ -- Bar라는 클래스를 받겠다는 것
this.bar = bar;
}
}
public class Bar { }
[applicationContext.xml]
<bean id="foo" class="Foo">
<constructor-arg>
<ref bean="bar" /> -- 여기의 bar의 값은 밑의 bar의 값을 의미한다. (밑에 있는 거 참조하겠다)
</constructor-arg>
</bean>
<bean id="bar" class="Bar" />
클래스 2개를 생성한다.
2. Setter Injection
: setter메소드를 이용하여 의존 관계를 연결시키는 것을 말한다.
: <property>요소의 name 속성을 이용하여 값의 의존 관계를 연결시킬 대상이 되는 필드값을 지정한다
① 전달인자가 2개 이상인 경우
기본데이터 타입일 경우에는 value 요소를 사용하여 의존관계를 연결시키기 위한 값을 지정
public class Foo {
private int a
private String b;
public void setA(int a) { }
public void setB(String b) { }
}
[applicationContext.xml]
<bean id="foo" class="Foo">
<property name="a">
<value>25</value>
</property>
<property name="b" value="Hello" />
</bean>
EL/JSTL → 메서드명을 변수명처럼 쓴다.
getName( )이거 할 때 ----> ${name} 이런식으로 쓴 것처럼
setA(int a) ------> a
property를 썼다는 것은 setter함수를 썼다는 것인데 name="a"라는 것은 a( )이게 아니라
앞에 접두사 set이 붙고 뒤에 괄호가 붙게 되는 것 이름은 A로 붙이고 ----> setA(int a)
setB(int b) ------> b 앞에 setter 빼고 뒤에 꼬리 빼는것 !!
② 객체를 전달할 경우에는 ref 요소를 사용
public class Foo {
private Bar bar;
public void setBar(Bar bar){
this.bar = bar;
}
}
public class Bar { }
클래스 2개 만들어줘야한다.
[applicationContext.xml]
<bean id="foo" class="Foo">
<property name="bar" ref="bar"></property> -- property를 썼다는 것은 setter 함수를 썼다는 것 !!
</bean>
<bean id="bar" class="Bar" />
bar는 setter 떼고 뒤에 꼬리 떼서 나온거 ---------> setBar(Bar bar)
[실습]
먼저 밑에 있는 프로젝트부터 만들기 !!
Project : Chapter02_ANNO
Project : Chapter02_XML
Chapter02_XML
pom.xml
복사해서 붙여넣기
pom.xml 전체코드
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Chapter02_XML</groupId>
<artifactId>Chapter02_XML</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.37</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
우린 sts에 lombok을 설정한 적이 없기 때문에 해줘야한다 !!
sts 끄고 !!
다시 sts 켜면 lombok도 연결되어있다 !!
Chapter02_ANNO
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Chapter02_ANNO</groupId>
<artifactId>Chapter02_ANNO</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.37</version>
</dependency>
</dependencies>
</project>
[실습]
Project : Chapter02_XML
Package : sample01
Interface : MessageBean.java
추상메소드 : public void sayHello();
public void sayHello(String fruit, int cost);
public void sayHello(String fruit, int cost, int qty);
Class : MessageBeanImpl.java - MessageBean.java Override 클래스
Class : HelloSpring.java - public static void main(String[] args)
src/main/resources : applicationContext.xml
MessageBean.java -- 인터페이스
package sample01;
public interface MessageBean {
public void sayHello();
public void sayHello(String fruit, int cost);
public void sayHello(String fruit, int cost, int qty);
}
MessageBeanImpl.java
fruit -- 생성자 생성
cost, qty -- setter 생성
package sample01;
public class MessageBeanImpl implements MessageBean {
private String fruit;
private int cost;
private int qty;
public MessageBeanImpl(String fruit) {
this.fruit = fruit;
}
public void setCost(int cost) {
this.cost = cost;
}
public void setQty(int qty) {
this.qty = qty;
}
@Override
public void sayHello() {
// TODO Auto-generated method stub
}
@Override
public void sayHello(String fruit, int cost) {
// TODO Auto-generated method stub
}
@Override
public void sayHello(String fruit, int cost, int qty) {
// TODO Auto-generated method stub
}
}
Lombok을 이용한 코드
package sample01;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@RequiredArgsConstructor
public class MessageBeanImpl implements MessageBean {
@NonNull
private String fruit;
@Setter
private int cost;
@Setter
private int qty;
/*
public MessageBeanImpl(String fruit) {
this.fruit = fruit;
}
public void setCost(int cost) {
this.cost = cost;
}
public void setQty(int qty) {
this.qty = qty;
}
*/
@Override
public void sayHello() {
System.out.println(fruit + "\t" + cost + "\t" + qty);
}
@Override
public void sayHello(String fruit, int cost) {
System.out.println(fruit + "\t" + cost + "\t" + qty);
}
@Override
public void sayHello(String fruit, int cost, int qty) {
System.out.println(fruit + "\t" + cost + "\t" + qty);
}
}
어떻게 소스가 흘러가고 메모리에 잡히는지가 중요하다 !!
applicationContext.xml
<bean id="messageBeanImpl" class="sample01.MessageBeanImpl"></bean>
이런식으로 new하면 기본생성자를 원하는데 우리가 아직 기본생성자를 잡은게 없어서 error가 뜬다.
생성자가 아예 없으면 기본생성자를 처리해주지만 우리는 생성자를 하나라도 만들어놨기 때문에
위에서 error가 뜨는 것이다.
MessageBeanImpl messageBeanImpl = new MessageBeanImpl("사과") --- 기본생성자
사과라는 default값을 주게 되면 된다.
밑에처럼 적으면 똑같은 거다 위에 코드랑 !!
<bean id="messageBeanImpl" class="sample01.MessageBeanImpl">
<constructor-arg>
<value>사과</value>
</constructor-arg>
</bean>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="messageBeanImpl" class="sample01.MessageBeanImpl">
<constructor-arg>
<value>사과</value>
</constructor-arg>
</bean>
</beans>
이렇게 되면 에러가 사라진다 !
이제 setter값도 전달해야된다 !
옛날 자바코드였으면
messageBeanImpl.setCost(5000);
messageBeanImpl.setQty(3);
이런식으로 적어야한다.
<property name="set메서드 이용"></property>
<property name="cost">
<value>5000</value> -- value 값으로 줘도되고
</property>
<property name="qty" value="3"></property> -- value 속성으로 줘도된다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="messageBeanImpl" class="sample01.MessageBeanImpl">
<constructor-arg>
<value>사과</value>
</constructor-arg>
<property name="cost">
<value>5000</value>
</property>
<property name="qty" value="3"></property>
</bean>
</beans>
HelloSpring.java
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
context.getBean("스프링 설정파일에서 만든 bean의 id 값 가져오기");
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MessageBean messageBean = context.getBean("messageBeanImpl", MessageBean.class);
messageBean.sayHello();
}
}
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MessageBean messageBean = context.getBean("messageBeanImpl", MessageBean.class);
messageBean.sayHello();
messageBean.sayHello("딸기", 10000);
}
}
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MessageBean messageBean = context.getBean("messageBeanImpl", MessageBean.class);
messageBean.sayHello();
messageBean.sayHello("딸기", 10000);
messageBean.sayHello("참외", 3500, 10);
}
}
Chapter02_ANNO
MessageBeanImpl.java -- 여긴 lombok 안 깔았으므로 다 지워준다 !!
package sample01;
public class MessageBeanImpl implements MessageBean {
private String fruit;
private int cost;
private int qty;
public MessageBeanImpl(String fruit) {
this.fruit = fruit;
}
public void setCost(int cost) {
this.cost = cost;
}
public void setQty(int qty) {
this.qty = qty;
}
@Override
public void sayHello() {
System.out.println(fruit + "\t" + cost + "\t" + qty);
}
@Override
public void sayHello(String fruit, int cost) {
System.out.println(fruit + "\t" + cost + "\t" + qty);
}
@Override
public void sayHello(String fruit, int cost, int qty) {
System.out.println(fruit + "\t" + cost + "\t" + qty);
}
}
Override라는 어노테이션에 에러가 뜬 이유는 버전이 낮아졌기 때문이다.
Project Facets를 먼저 바꾸고
Build Path로 들어가서 ! 바꿔야한다.
에러가 사라진 거 확인할 수 있음 !
이제 어노테이션으로 바꾸자 !
MessageBeanImpl.java -- @Component
오른쪽에서 썼던 코드가 왼쪽에서처럼 바뀌는 것 !!
public MessageBeanImpl(@Value("사과") String fruit) {
this.fruit = fruit;
}
public void setCost(@Value("5000") int cost) {
this.cost = cost;
}
public void setQty(@Value("3") int qty) {
this.qty = qty;
}
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="sample01" />
</beans>
HelloSpring.java
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MessageBean messageBean = context.getBean("messageBeanImpl", MessageBean.class);
messageBean.sayHello();
messageBean.sayHello("딸기", 10000);
messageBean.sayHello("참외", 3500, 10);
}
}
스프링에서 설정한게 안들어와진다.
사과라는 값은 대신 들어온다.
MessageBeanImpl.java -- @Autowired
@Autowired
public void setCost(@Value("5000") int cost) {
this.cost = cost;
}
@Autowired
public void setQty(@Value("3") int qty) {
this.qty = qty;
}
- @Autowired: Spring 컨테이너가 의존성을 자동으로 주입할 수 있도록 한다.
- 이 코드에서 Spring은 setCost와 setQty 메서드를 통해 값을 자동으로 주입하여 필드(cost, qty)를 초기화한다.
Project : Chapter02_ANNO
Package : spring.conf
Class : SpringConfiguration.java
우리가 빈을 생성하는 방법
1. <bean ~~> -- xml로 생성
2. @Component
@Bean
SpringConfiguration.java -- @Configuration (일반 자바파일이 아닌 스프링 파일이다.)
즉, 스프링 설정파일이다.
package spring.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import sample01.MessageBeanImpl;
@Configuration
public class SpringConfiguration {
}
<context:component-scan base-package="spring.conf" /> -- 모든 설정이 spring.conf 여기서 일어나게 할 것이므로
<context:component-scan base-package="sample01" /> 얘는 주석처리 해도된다. 일단은 살려둔다.
MessageBeanImpl.java -- //@Component 주석처리해주기
//@Component
public class MessageBeanImpl implements MessageBean {
private String fruit;
private int cost;
private int qty;
@Bean
- 메서드에서 return 되는 값을 스프링의 bean으로 생성한다.
- 메서드명은 반드시 bean의 id명으로 해야한다. -- messageBeanImpl
- 메서드명을 자바처럼 getter로 사용하려면 @Bean(name="")를 사용해야한다.
원래는 현재 MessageBeanImpl라는 클래스를 bean으로 생성해주세요 이렇게 했는데
이제는 메서드에서 return 되는 값을 스프링의 bean으로 생성한다.
@Component는 클래스 위에 잡혔다면
@Bean은 메소드의 위에 잡힌다.
SpringConfiguration.java
- 첫 번째 방법
package spring.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import sample01.MessageBeanImpl;
@Configuration
public class SpringConfiguration {
@Bean
public MessageBeanImpl messageBeanImpl(){
return new MessageBeanImpl("사과");
}
- 두 번째 방법
package spring.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import sample01.MessageBeanImpl;
@Configuration
public class SpringConfiguration {
/*
* @Bean public MessageBeanImpl messageBeanImpl(){ return new
* MessageBeanImpl("사과"); }
*/
@Bean(name="messageBeanImpl")
public MessageBeanImpl getMessageBeanImpl(){
return new MessageBeanImpl("사과");
}
}
원래 return 할 때는 앞에 접두사 get이 붙여진다.
public String getName( ) {
return naem;
}
get이라는 메소드는 return 값이 반드시 생긴다.
자바처럼
@Bean
public MessageBeanImpl getMessageBeanImpl(){
return new MessageBeanImpl("사과");
}
이렇게 가고싶다는 것 하지만 이렇게 하면 bean으로 생성이 안된다.
메서드명은 반드시 bean의 id명으로 해야하므로
MessageBeanImpl getMessageBeanImpl = new MessageBeanImpl ("사과"); 와 똑같은 역할이라는 것이다.
이러면 스프링이 얘를 인식을 못하게된다.
@Bean(name="messageBeanImpl")
public MessageBeanImpl getMessageBeanImpl(){
return new MessageBeanImpl("사과");
}
이런식으로 name를 지정해줘야한다.
@Bean
public CalcMul getcalcMul () {
return new CalcMul();
}
CalcMul getcalcMul = new CalcMul();
위에 빈의 이름을 안주게 되면 찾지 못하게된다.
[문제1]
Project : chapter02_XML / chapete02_ANNO / SpringConfiguration.java
Package : sample02
Interface : Calc.java
추상Method : public void calculate();
Class : HelloSpring - public static void main(String[] args)
CalcAdd.java - 필드 x, y 설정
CalcMul.java - 필드 x, y 설정
[실행결과]
25 + 36 = xx
→ xml에서 CalcAdd를 빈(add)으로 Constructor Injection
25 * 36 = xx
→ xml에서 CalcMul를 빈(mul)으로 Setter Injection
chapter02_XML
Calc.java -- 인터페이스
package sample02;
public interface Calc {
public void calculate();
}
CalcAdd.java - 필드 x, y 설정 -- 생성자 생성하기
package sample02;
public class CalcAdd implements Calc {
private int x, y;
public CalcAdd(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public void calculate() {
System.out.println(x + " + " + y + " = " + (x+y));
}
}
- lombok 사용한 코드
package sample02;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class CalcAdd implements Calc {
private int x, y;
@Override
public void calculate() {
System.out.println(x + " + " + y + " = " + (x+y));
}
}
applicationContext.xml -- xml에서 CalcAdd를 빈(add)으로 Constructor Injection
<bean id="calcAdd" class="sample02.CalcAdd">
<constructor-arg value="25"/>
<constructor-arg value="36"/>
</bean>
CalcMul.java - 필드 x, y 설정 -- setter 생성하기
package sample02;
public class CalcMul implements Calc {
private int x, y;
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
@Override
public void calculate() {
System.out.println(x + " * " + y + " = " + (x*y));
}
}
applicationContext.xml -- xml에서 CalcMul를 빈(mul)으로 Setter Injection
<bean id="calcMul" class="sample02.CalcMul">
<property name="x" value="25"/>
<property name="y" value="36"/>
</bean>
HelloSpring.java
package sample02;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Calc calc;
calc = context.getBean("calcAdd", Calc.class);
calc.calculate();
calc = context.getBean("calcMul", Calc.class);
calc.calculate();
}
}
chapete02_ANNO
applicationContext.xml
<context:component-scan base-package="sample02" />
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="sample01" />
<context:component-scan base-package="sample02" />
<context:component-scan base-package="spring.conf" />
</beans>
위에 코드는 빈을 설정해주는 것이 아니다.
빈 설정을 위해서 어노테이션을 썼다. 위에 적은 페이지에서 어노테이션으로 빈을 설정한다.라고 선언하는 것
패키지를 몽땅 뒤져서 어노테이션으로 컴포넌트를 적은 것을 다 빈으로 설정해주겠다.
@Configuration -- 얘는 스프링 설정파일, 일반 자바파일이 아닌 (환경설정파일)이다라고 표시해놓은 것
위에 저걸 적었기에 @Bean이 먹히는 것이다.
@Bean은 메서드 위에
@Component는 클래스 위에
CalcAdd.java -- @Component
public CalcAdd(@Value("25") int x, @Value("36") int y)
package sample02;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class CalcAdd implements Calc {
private int x, y;
public CalcAdd(@Value("25") int x, @Value("36") int y) {
this.x = x;
this.y = y;
}
@Override
public void calculate() {
System.out.println(x + " + " + y + " = " + (x+y));
}
}
CalcMul.java -- @Component
@Autowired
public void setX(@Value("25") int x) {
this.x = x;
}
@Autowired
public void setY(@Value("36") int y) {
this.y = y;
}
생성자는 자동호출하지만
set은 자동호출을 안 하기 때문에 Autowired를 붙여야된다.
package sample02;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class CalcMul implements Calc {
private int x, y;
@Autowired
public void setX(@Value("25") int x) {
this.x = x;
}
@Autowired
public void setY(@Value("36") int y) {
this.y = y;
}
@Override
public void calculate() {
System.out.println(x + " * " + y + " = " + (x*y));
}
}
SpringConfiguration.java
CalcAdd.java / CalcMul.java에서 @Component를 주석처리 해보자 !
package spring.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import sample01.MessageBeanImpl;
import sample02.CalcAdd;
import sample02.CalcMul;
@Configuration
public class SpringConfiguration {
/*
* @Bean public MessageBeanImpl messageBeanImpl(){ return new
* MessageBeanImpl("사과"); }
*/
@Bean(name="messageBeanImpl")
public MessageBeanImpl getMessageBeanImpl(){
return new MessageBeanImpl("사과");
}
@Bean(name="calcAdd")
public CalcAdd calcAdd() {
return new CalcAdd(25, 36);
}
@Bean
public CalcMul calcMul() {
return new CalcMul();
}
}
CalcAdd에는 기본생성자가 없기 때문에 데이터 값을 넣어줘야한다.
CalcMul에는 아무런 생성자가 없기 때문에 기본생성자가 자동으로 생성되므로 값을 넣어주지 않아도 되는 것이다.
[문제2] 다음의 조건에 맞게 이름, 국어, 영어, 수학의 데이터를 입력하여
총점과 평균을 구하시오
* 조건
1. [Chapter02_XML] 에서는 XML를 이용한 빈 생성 한다
[Chapter02_ANNO] 에서는 어노테이션을 이용한 빈 생성 한다
2. SungJukDTO는 Setter Injection을 사용 한다
SungJukImpl 클래스는 Constructor Injection을 사용 한다
3. SungJukDTO의 필드는 name, kor, eng, math, tot, avg를 사용 한다
Project : Chapter02_XML
Package : sample03
Class : HelloSpring.java - public static void main(String[] args)
Interface : SungJuk.java
추상Method : public void calcTot(); //총점 계산
public void calcAvg(); //평균 계산
public void display(); //출력
public void modify(); //수정
Class : SungJukImpl.java - SungJuk.java를 Override한 클래스
- Constructor Injection
Class : SungJukDTO.java - Setter Injection
[실행결과]
이름 국어 영어 수학 총점 평균
홍길동 97 100 95 xxx xx.xx
* 수정 - modify()에서 처리
이름 입력 : 코난
국어 입력 : 100
영어 입력 : 100
수학 입력 : 95
이름 국어 영어 수학 총점 평균
코난 100 100 95 xxx xx.xx
[Chapter02_XML] - sample03
SungJukDTO.java
package sample03;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class SungJukDTO {
private String name;
private int kor;
private int eng;
private int math;
private int tot;
private double avg;
@Override
public String toString() {
return name + "\t"
+ kor + "\t"
+ eng + "\t"
+ math + "\t"
+ tot + "\t"
+ String.format("%.2f", avg);
}
}
SungJuk.java -- 인터페이스
package sample03;
public interface SungJuk {
public void calcTot(); //총점 계산
public void calcAvg(); //평균 계산
public void display(); //출력
public void modify(); //수정
}
SungJukImpl.java - SungJuk.java를 Override한 클래스 - Constructor Injection
package sample03;
import java.util.Scanner;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class SungJukImpl implements SungJuk {
private SungJukDTO sungJukDTO = null;
/*
* public SungJukImpl(SungJukDTO sungJukDTO) { this.sungJukDTO = sungJukDTO; }
*/
@Override
public void calcTot() {
int tot = sungJukDTO.getKor() + sungJukDTO.getEng() + sungJukDTO.getMath();
sungJukDTO.setTot(tot);
}
@Override
public void calcAvg() {
double avg = sungJukDTO.getTot() / 3.0;
sungJukDTO.setAvg(avg);
}
@Override
public void display() {
System.out.println("이름\t국어\t영어\t수학\t총점\t평균");
System.out.println(sungJukDTO);
}
@Override
public void modify() {
Scanner scan = new Scanner(System.in);
System.out.print("이름 입력: ");
sungJukDTO.setName(scan.next());
System.out.print("국어 입력: ");
sungJukDTO.setKor(scan.nextInt());
System.out.print("영어 입력: ");
sungJukDTO.setEng(scan.nextInt());
System.out.print("수학 입력: ");
sungJukDTO.setMath(scan.nextInt());
calcTot();
calcAvg();
display();
}
}
applicationContext.xml
xml은 코드를 한꺼번에 읽는다. 쭉 읽고 메모리에 다 올리는 것 이다.
내가 원하는 부분만 실행한다. 실행을 원하지 않는 부분은 주석 걸어놔야한다.
sungJukDTO에는 SETTER을 걸어놨으므로 property해주기 !
SungJukImpl는 @AllArgsConstructor 생성자이므로 constructor 해주길 원한다.
<!-- sample03 -->
<bean id="sungJukImpl" class="sample03.SungJukImpl">
<constructor-arg ref="sungJukDTO"/>
</bean>
<bean id="sungJukDTO" class="sample03.SungJukDTO">
<property name="name" value="홍길동" />
<property name="kor" value="97" />
<property name="eng" value="100" />
<property name="math" value="95" />
</bean>
참조하겠다.
HelloSpring.java
package sample03;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SungJuk sungJuk = (SungJuk) context.getBean("sungJukImpl");
sungJuk.calcTot();
sungJuk.calcAvg();
sungJuk.display();
System.out.println();
System.out.println("*** 수정 ***");
sungJuk.modify();
}
}
[Chapter02_ANNO] - sample03
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="sample01" />
<context:component-scan base-package="sample02" />
<context:component-scan base-package="sample03" />
<context:component-scan base-package="spring.conf" />
</beans>
SungJukDTO.java -- @Component
@Value("코난") String name
@Value("100") int kor
@Value("100") int eng
@Value("95") int math
package sample03;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class SungJukDTO {
private String name;
private int kor;
private int eng;
private int math;
private int tot;
private double avg;
public String getName() {
return name;
}
public void setName(@Value("홍길동") String name) {
this.name = name;
}
public int getKor() {
return kor;
}
public void setKor(@Value("100") int kor) {
this.kor = kor;
}
public int getEng() {
return eng;
}
public void setEng(@Value("100") int eng) {
this.eng = eng;
}
public int getMath() {
return math;
}
public void setMath(@Value("95") int math) {
this.math = math;
}
public int getTot() {
return tot;
}
public void setTot(int tot) {
this.tot = tot;
}
public double getAvg() {
return avg;
}
public void setAvg(double avg) {
this.avg = avg;
}
}
SungJukImpl.java -- @Component
package sample03;
import java.util.Scanner;
import org.springframework.stereotype.Component;
@Component
public class SungJukImpl implements SungJuk {
private SungJukDTO sungJukDTO = null;
public SungJukImpl(SungJukDTO sungJukDTO) {
this.sungJukDTO = sungJukDTO;
}
@Override
public void calcTot() {
int tot = sungJukDTO.getKor() + sungJukDTO.getEng() + sungJukDTO.getMath();
sungJukDTO.setTot(tot);
}
@Override
public void calcAvg() {
double avg = sungJukDTO.getTot() / 3.0;
sungJukDTO.setAvg(avg);
}
@Override
public void display() {
System.out.println("이름\t국어\t영어\t수학\t총점\t평균");
System.out.println(sungJukDTO);
}
@Override
public void modify() {
Scanner scan = new Scanner(System.in);
System.out.print("이름 입력: ");
sungJukDTO.setName(scan.next());
System.out.print("국어 입력: ");
sungJukDTO.setKor(scan.nextInt());
System.out.print("영어 입력: ");
sungJukDTO.setEng(scan.nextInt());
System.out.print("수학 입력: ");
sungJukDTO.setMath(scan.nextInt());
calcTot();
calcAvg();
display();
}
}
생성자 setter 다 안써도 된다. 그냥 가서 주입하라는 것 !
SungJukDTO.java
여기 set에 @Autowired 안 걸어도 된다 했는데 일단은 걸어야된다,,,, 보류
package sample03;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class SungJukDTO {
private String name;
private int kor;
private int eng;
private int math;
private int tot;
private double avg;
public String getName() {
return name;
}
@Autowired
public void setName(@Value("홍길동") String name) {
this.name = name;
}
public int getKor() {
return kor;
}
@Autowired
public void setKor(@Value("100") int kor) {
this.kor = kor;
}
public int getEng() {
return eng;
}
@Autowired
public void setEng(@Value("100") int eng) {
this.eng = eng;
}
pub
lic int getMath() {
return math;
}
@Autowired
public void setMath(@Value("95") int math) {
this.math = math;
}
public int getTot() {
return tot;
}
public void setTot(int tot) {
this.tot = tot;
}
public double getAvg() {
return avg;
}
public void setAvg(double avg) {
this.avg = avg;
}
@Override
public String toString() {
return name + "\t"
+ kor + "\t"
+ eng + "\t"
+ math + "\t"
+ tot + "\t"
+ String.format("%.2f", avg);
}
}
@Bean으로 생성
SungJukImpl.java / SungJukDTO.java - @Component 주석처리
SpringConfiguration.java
@Configuration 잡은 이유
: 이 파일은 일반 자바파일이 아니라 스프링에서 사용하는 환경설정 파일입니다를 알려주는 것
//sample03
@Bean
public SungJukDTO sunJukDTO() {
return new SungJukDTO();
}
@Bean
public SungJukImpl sungJukImpl() {
return new SungJukImpl();
}
}
'Spring' 카테고리의 다른 글
DAY 63 - 스프링 프레임워크 - AOP (2024.10.04) (0) | 2024.10.04 |
---|---|
DAY 62 - 스프링 프레임워크 - 파일출력 (2024.10.02) (1) | 2024.10.02 |
DAY 61 - 스프링 프레임워크 HOMEWORK (2024.10.01) (2024.10.02) (0) | 2024.10.02 |
DAY 60 - 스프링 프레임 워크 HOMEWORK (2024.09.30) (2) | 2024.09.30 |
DAY 60 - 스프링 프레임워크 (2024.09.30) (1) | 2024.09.30 |