Spring DI 이론
메타 애너테이션 : 애너테이션@ 을 만들때 사용하는 애너테이션
Bean : spring contain가 관리하는 객체
Spring container : 빈의 저장소, 빈을 저장 관리
1. Bean Factory : 빈을 생성 연결 등의 기본 기능을 정의
2. Application context : BeanFactory를 확장해서 여러 기능을 추가
AC 종류 | XML | Java 코드 |
non-Web | GenericXml ApplicationContext | AnnotationConfig ApplicationContext |
Web | XmlWeb ApplicationContext | AnnotationConfigWeb ApplicationContext |
<component-scan>으로 @Component 가 클래스를 자동 검색해서 빈으로 등록한다.
config.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.xsd">
<!-- @Autowired 사용하려면 필수 -->
<context:annotation-config />
<!-- com ( component-scan ) -->
<!-- 패키지 안에 있는 클래스 중에서 @Component 붙은것을 찾아서 Bean 으로 등록 -->
<context:component-scan base-package="com.test.ch3" >
<!-- ex 입력시 빠른 입력 가능 -->
<!-- 제외 할 것들 -->
<context:exclude-filter type="regex" expression="com.test.ch3.dpCopy*.*"/>
</context:component-scan>
</beans>
=====================================================
//@Component("superEngine")
@Component
clsss SuperEngine extends Engine {}
빈 관련된..
package com.test.ch3;
import org.springframework.beans.factory.annotation.*;
import org.springframework.context.*;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.*;
import org.springframework.stereotype.*;
import javax.inject.*;
import java.util.*;
@Component
@Scope("prototype")
class Door {}
@Component class Engine {}
@Component class TurboEngine extends Engine {}
@Component class SuperEngine extends Engine {}
@Component
class Car {
@Value("red") String color;
@Value("100") int oil;
@Autowired Engine engine;
@Autowired Door[] doors;
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", oil=" + oil +
", engine=" + engine +
", doors=" + Arrays.toString(doors) +
'}';
}
}
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
// Car car = ac.getBean("car", Car.class); // 타입을 지정하면 형변환 안해도됨. 아래의 문장과 동일
Car car = (Car) ac.getBean("car"); // 이름으로 빈 검색
Car car2 = (Car) ac.getBean(Car.class); // 타입으로 빈 검색
System.out.println("car = " + car);
System.out.println("car2 = " + car2);
System.out.println("ac.getBeanDefinitionNames() = " + Arrays.toString(ac.getBeanDefinitionNames())); // 정의된 빈의 이름을 배열로 반환
System.out.println("ac.getBeanDefinitionCount() = " + ac.getBeanDefinitionCount()); // 정의된 빈의 개수를 반환
System.out.println("ac.containsBeanDefinition(\"car\") = " + ac.containsBeanDefinition("car")); // true 빈의 정의가 포함되어 있는지 확인
System.out.println("ac.containsBean(\"car\") = " + ac.containsBean("car")); // true 빈이 포함되어 있는지 확인
System.out.println("ac.getType(\"car\") = " + ac.getType("car")); // 빈의 이름으로 타입을 알아낼 수 있음.
System.out.println("ac.isSingleton(\"car\") = " + ac.isSingleton("car")); // true 빈이 싱글톤인지 확인
System.out.println("ac.isSingleton(\"car\") = " + ac.isPrototype("car")); // false 빈이 프로토타입인지 확인
System.out.println("ac.isPrototype(\"door\") = " + ac.isPrototype("door")); // true
System.out.println("ac.isTypeMatch(\"car\", Car.class) = " + ac.isTypeMatch("car", Car.class)); // "car"라는 이름의 빈의 타입이 Car인지 확인
System.out.println("ac.findAnnotationOnBean(\"car\", Component.class) = " + ac.findAnnotationOnBean("car", Component.class)); // 빈 car에 @Component가 붙어있으면 반환
System.out.println("ac.getBeanNamesForAnnotation(Component.class) = " + Arrays.toString(ac.getBeanNamesForAnnotation(Component.class))); // @Component가 붙은 빈의 이름을 배열로 반환
System.out.println("ac.getBeanNamesForType(Car.class) = " + Arrays.toString(ac.getBeanNamesForType(Engine.class))); // Engine 또는 그 자손 타입인 빈의 이름을 배열로 반환
}
}
//===================================================
car = Car{color='red', oil=100, engine=com.test.ch3.Engine@6cdba6dc, doors=[com.test.ch3.Door@6531a794]}
car2 = Car{color='red', oil=100, engine=com.test.ch3.Engine@6cdba6dc, doors=[com.test.ch3.Door@6531a794]}
ac.getBeanDefinitionNames() = [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, car, door, engine, homeController, superEngine, turboEngine]
ac.getBeanDefinitionCount() = 12
ac.containsBeanDefinition("car") = true
ac.containsBean("car") = true
ac.getType("car") = class com.test.ch3.Car
ac.isSingleton("car") = true
ac.isSingleton("car") = false
ac.isPrototype("door") = true
ac.isTypeMatch("car", Car.class) = true
ac.findAnnotationOnBean("car", Component.class) = @org.springframework.stereotype.Component(value="")
ac.getBeanNamesForAnnotation(Component.class) = [car, door, engine, homeController, superEngine, turboEngine]
ac.getBeanNamesForType(Car.class) = [engine, superEngine, turboEngine]
@Autowired WebApplicationContext servletAC; // Servlet AC
ServletContext sc = request.getSession().getServletContext(); // ApplicationContextFacade // Root AC
WebApplicationContext rootAC = WebApplicationContextUtils.getWebApplicationContext(sc);
servletAC 의 부모 rootAC
System.out.println("servletAC.getParent()==rootAC = " + (servletAC.getParent() == rootAC));
import java.util.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.context.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.*;
import org.springframework.web.context.support.*;
import javax.servlet.*;
import javax.servlet.http.*;
@Controller
public class HomeController {
@Autowired
WebApplicationContext servletAC; // Servlet AC
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, HttpServletRequest request, Model model) {
// 원래는 request.getServletContext()지만, 컨트롤러는 HttpServlet을 상속받지 않아서 아래와 같이 해야함.
ServletContext sc = request.getSession().getServletContext(); // ApplicationContextFacade
WebApplicationContext rootAC = WebApplicationContextUtils.getWebApplicationContext(sc); // Root AC
System.out.println("webApplicationContext = " + rootAC);
System.out.println("servletAC = " + servletAC);
System.out.println("rootAC.getBeanDefinitionNames() = " + Arrays.toString(rootAC.getBeanDefinitionNames()));
System.out.println("servletAC.getBeanDefinitionNames() = " + Arrays.toString(servletAC.getBeanDefinitionNames()));
System.out.println("rootAC.getBeanDefinitionCount() = " + rootAC.getBeanDefinitionCount());
System.out.println("servletAC.getBeanDefinitionCount() = " + servletAC.getBeanDefinitionCount());
System.out.println("servletAC.getParent()==rootAC = " + (servletAC.getParent() == rootAC)); // servletAC.getParent()==rootAC = true
return "home";
}
}
//===================================================
webApplicationContext = Root WebApplicationContext: startup date [Tue Mar 08 09:51:40 KST 2022]; root of context hierarchy
servletAC = WebApplicationContext for namespace 'appServlet-servlet': startup date [Tue Mar 08 09:51:44 KST 2022]; parent: Root WebApplicationContext
rootAC.getBeanDefinitionNames() = []
servletAC.getBeanDefinitionNames() = [mvcContentNegotiationManager, org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,
mvcCorsConfigurations, org.springframework.format.support.FormattingConversionServiceFactoryBean#0,
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter, mvcUriComponentsContributor, org.springframework.web.servlet.handler.MappedInterceptor#0,
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0, org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0,
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0, org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping, org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter, mvcHandlerMappingIntrospector, mvcResourceUrlProvider, org.springframework.web.servlet.handler.MappedInterceptor#1, mvcPathMatcher,
mvcUrlPathHelper, org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0, org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0, org.springframework.web.servlet.view.InternalResourceViewResolver#0,
car, door, engine, homeController, superEngine, turboEngine, org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor,
org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor,
org.springframework.context.event.internalEventListenerFactory]
rootAC.getBeanDefinitionCount() = 0
servletAC.getBeanDefinitionCount() = 33
servletAC.getParent()==rootAC = true
root-applicationContext
servlet-Context
root-applicationContext 와 servlet-Context 가 초기화 되는지 확인한다.
DI - 사용할 객체를 외부에서 주입받는것
IOC 제어의 역전 - 제어의 흐름이 프레임워크에 있음
또한 주입받아야 하는 빈은 생성자를 이용하여 주입하는 것이 좋다.
@Autowired Engine engine; ( X )
@Autowired public Car ( @Value("red") String color , Door[] door ){ ~~ } ( O )
@Component
@Scope("prototype")
class Door {}
@Component class Engine {}
@Component class TurboEngine extends Engine {}
@Component class SuperEngine extends Engine {}
@Component
class Car {
@Value("red") String color;
@Value("100") int oil;
//@Autowired
Engine engine;
//@Autowired
Door[] doors;
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", oil=" + oil +
", engine=" + engine +
", doors=" + Arrays.toString(doors) +
'}';
}
}
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = (Car) ac.getBean("car"); // 이름으로 빈 검색
System.out.println("car = " + car);
}
}
//======================================================
주입하지 않은 빈은 null 로 된다.
car = Car{color='red', oil=100, engine=null, doors=null}
@Component
@Scope("prototype")
class Door {}
@Component class Engine {}
@Component class TurboEngine extends Engine {}
@Component class SuperEngine extends Engine {}
@Component
class Car {
@Value("red") String color;
@Value("100") int oil;
//@Autowired
Engine engine;
//@Autowired
Door[] doors;
@Autowired
public Car( @Value("red") String color, @Value("100") int oil, Engine engine, Door[] doors) {
this.color = color;
this.oil = oil;
this.engine = engine;
this.doors = doors;
}
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", oil=" + oil +
", engine=" + engine +
", doors=" + Arrays.toString(doors) +
'}';
}
}
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = (Car) ac.getBean("car"); // 이름으로 빈 검색
System.out.println("car = " + car);
}
}
//====================================================
생성자를 이용하여 주입
car = Car{color='red', oil=100, engine=com.test.ch3.Engine@3eb81efb, doors=[com.test.ch3.Door@3b5fad2d]}
class Engine{} 에 @Component (빈 등록) 이 되어 있지 않은 상태에서
@Autowired Engine engine; 여기서 타입 검색을 먼저 하는데 빈으로 등록된 superEngine , turboEngine 둘중에
무엇을 선택해야 될지 모르겠고 이름으로 조회해도 engine이 빈에 등록되어 있지 않아서 에러를 발생함.
이런 경우 @Autowired 아래에 @Qualifier("superEngine") 를 이용하여
빈으로 등록된 후보 중에서 하나를 지정해 주어야 한다.
아니면 주입받을 의존객체가 필수적이지 않을 경우 @Autowired(required = false)로 설정해서
의존객체를 주입받지 못하더라도 빈을 생성하도록 할 수 있다.
또는 @Resource(name="superEngine") 이렇게 이름검색을 이용해도 된다.
@Value 와 @PropertySource
- 외부 파일로 부터 값을 불러 와서 @Value 에 주입 할 수 있다. ( setting.properties 파일 )
- 시스템 환경변수 모두 불러오기 ( 현재 작업 디렉토리 등을 불러 올 수 있음 )
- 프로퍼티 값 모두 불러오기( timezone[한국음GMT +9] 등.. )
@Component
@Scope("prototype")
class Door {}
@Component class Engine {}
@Component class TurboEngine extends Engine {}
@Component class SuperEngine extends Engine {}
@Component
class Car {
@Value("red") String color;
@Value("100") int oil;
//@Autowired
Engine engine;
//@Autowired
Door[] doors;
@Autowired
public Car( @Value("red") String color, @Value("100") int oil, Engine engine, Door[] doors) {
this.color = color;
this.oil = oil;
this.engine = engine;
this.doors = doors;
}
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", oil=" + oil +
", engine=" + engine +
", doors=" + Arrays.toString(doors) +
'}';
}
}
@Component
@PropertySource("setting.properties")
class SysInfo{
@Value("#{systemProperties['user.timezone']}")
String timeZone;
@Value("#{systemEnvironment['APPDATA']}")
String currDir;
// 외부 파일로 부터 값을 불러 올 수 있다.
// setting.properties
@Value("${autosaveDir}")
String autosaveDir;
@Value("${autosaveInterval}")
int autosaveInterval;
@Value("${autosave}")
boolean autosave;
@Override
public String toString() {
return "SysInfo{" +
"timeZone='" + timeZone + '\'' +
", currDir='" + currDir + '\'' +
", autosaveDir='" + autosaveDir + '\'' +
", autosaveInterval=" + autosaveInterval +
", autosave=" + autosave +
'}';
}
}
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
Car car = (Car) ac.getBean("car"); // 이름으로 빈 검색
System.out.println("car = " + car);
System.out.println("ac.getBean(SysInfo.class) = " + ac.getBean(SysInfo.class));
Map<String, String> map = System.getenv(); // 시스템 환경변수 모두 불러오기 ( 현재 작업 디렉토리 등을 불러 올 수 있음 )
System.out.println("map = " + map);
Properties properties = System.getProperties(); // 프로퍼티 값 모두 불러오기( timezone[한국음GMT +9] 등.. )
System.out.println("properties = " + properties);
}
}
//==========================================
car = Car{color='red', oil=100, engine=com.test.ch3.Engine@a3d9978, doors=[com.test.ch3.Door@24c22fe]}
ac.getBean(SysInfo.class) = SysInfo{timeZone='Asia/Seoul', currDir='C:\Users\back8\AppData\Roaming', autosaveDir='/autosave', autosaveInterval=30, autosave=true}
map = {USERDOMAIN_ROAMINGPROFILE=LAPTOP-4HP6BLD0, LOCALAPPDATA=C:\Users\back8\AppData\Local, PROCESSOR_LEVEL=6, IntelliJ IDEA=C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.3\bin;, USERDOMAIN=LAPTOP-4HP6BLD0, FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer, LOGONSERVER=\\LAPTOP-4HP6BLD0, JAVA_HOME=C:\jdk11, SESSIONNAME=Console, ALLUSERSPROFILE=C:\ProgramData, PROCESSOR_ARCHITECTURE=AMD64, PSModulePath=C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules, SystemDrive=C:, OneDrive=C:\Users\back8\OneDrive, APPDATA=C:\Users\back8\AppData\Roaming, USERNAME=back8, TOMCAT_HOME=C:\apache-tomcat-9.0.55, ProgramFiles(x86)=C:\Program Files (x86), CommonProgramFiles=C:\Program Files\Common Files, Path=C:\jdk11\bin;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\iCLS\;C:\Program Files\Intel\Intel(R) Management Engine Components\iCLS\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\xampp\php;C:\composer;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\dotnet\;C:\Program Files\Microsoft VS Code\bin;C:\Program Files\MySQL\MySQL Server 8.0\bin;C:\Program Files\Git\cmd;C:\Program Files\MySQL\MySQL Shell 8.0\bin\;C:\Users\back8\AppData\Local\Microsoft\WindowsApps;C:\Users\back8\AppData\Roaming\Composer\vendor\bin;C:\Users\back8\.dotnet\tools;C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.3\bin;, FPS_BROWSER_USER_PROFILE_STRING=Default, PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC, DriverData=C:\Windows\System32\Drivers\DriverData, OS=Windows_NT, COMPUTERNAME=LAPTOP-4HP6BLD0, PROCESSOR_REVISION=8e09, CommonProgramW6432=C:\Program Files\Common Files, ComSpec=C:\WINDOWS\system32\cmd.exe, TMPDIR=C:\Users\Public\Documents\ESTsoft\CreatorTemp, ProgramData=C:\ProgramData, ProgramW6432=C:\Program Files, HOMEPATH=\Users\back8, SystemRoot=C:\WINDOWS, TEMP=C:\Users\back8\AppData\Local\Temp, HOMEDRIVE=C:, PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 142 Stepping 9, GenuineIntel, USERPROFILE=C:\Users\back8, TMP=C:\Users\back8\AppData\Local\Temp, CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files, ProgramFiles=C:\Program Files, PUBLIC=C:\Users\Public, NUMBER_OF_PROCESSORS=4, VS160COMCOMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\, windir=C:\WINDOWS, =::=::\, IDEA_INITIAL_DIRECTORY=C:\Users\back8\Desktop}
properties = {sun.desktop=windows, awt.toolkit=sun.awt.windows.WToolkit, java.specification.version=11, sun.cpu.isalist=amd64, sun.jnu.encoding=MS949, java.class.path=C:\java-project\ch3\target\classes;C:\Users\back8\.m2\repository\org\springframework\spring-context\5.0.7.RELEASE\spring-context-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\springframework\spring-aop\5.0.7.RELEASE\spring-aop-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\springframework\spring-beans\5.0.7.RELEASE\spring-beans-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\springframework\spring-core\5.0.7.RELEASE\spring-core-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\springframework\spring-jcl\5.0.7.RELEASE\spring-jcl-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\springframework\spring-expression\5.0.7.RELEASE\spring-expression-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\springframework\spring-webmvc\5.0.7.RELEASE\spring-webmvc-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\springframework\spring-web\5.0.7.RELEASE\spring-web-5.0.7.RELEASE.jar;C:\Users\back8\.m2\repository\org\aspectj\aspectjrt\1.6.10\aspectjrt-1.6.10.jar;C:\Users\back8\.m2\repository\org\slf4j\slf4j-api\1.6.6\slf4j-api-1.6.6.jar;C:\Users\back8\.m2\repository\org\slf4j\jcl-over-slf4j\1.6.6\jcl-over-slf4j-1.6.6.jar;C:\Users\back8\.m2\repository\org\slf4j\slf4j-log4j12\1.6.6\slf4j-log4j12-1.6.6.jar;C:\Users\back8\.m2\repository\log4j\log4j\1.2.15\log4j-1.2.15.jar;C:\Users\back8\.m2\repository\javax\inject\javax.inject\1\javax.inject-1.jar;C:\Users\back8\.m2\repository\javax\servlet\jstl\1.2\jstl-1.2.jar;C:\Users\back8\.m2\repository\com\google\guava\guava\31.1-jre\guava-31.1-jre.jar;C:\Users\back8\.m2\repository\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;C:\Users\back8\.m2\repository\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\back8\.m2\repository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;C:\Users\back8\.m2\repository\org\checkerframework\checker-qual\3.12.0\checker-qual-3.12.0.jar;C:\Users\back8\.m2\repository\com\google\errorprone\error_prone_annotations\2.11.0\error_prone_annotations-2.11.0.jar;C:\Users\back8\.m2\repository\com\google\j2objc\j2objc-annotations\1.3\j2objc-annotations-1.3.jar;C:\apache-tomcat-9.0.55\lib\el-api.jar;C:\apache-tomcat-9.0.55\lib\jasper.jar;C:\apache-tomcat-9.0.55\lib\jsp-api.jar;C:\apache-tomcat-9.0.55\lib\catalina.jar;C:\apache-tomcat-9.0.55\lib\ecj-4.20.jar;C:\apache-tomcat-9.0.55\lib\jasper-el.jar;C:\apache-tomcat-9.0.55\lib\jaspic-api.jar;C:\apache-tomcat-9.0.55\lib\tomcat-api.jar;C:\apache-tomcat-9.0.55\lib\tomcat-jni.jar;C:\apache-tomcat-9.0.55\lib\catalina-ha.jar;C:\apache-tomcat-9.0.55\lib\servlet-api.jar;C:\apache-tomcat-9.0.55\lib\tomcat-dbcp.jar;C:\apache-tomcat-9.0.55\lib\tomcat-jdbc.jar;C:\apache-tomcat-9.0.55\lib\tomcat-util.jar;C:\apache-tomcat-9.0.55\lib\catalina-ant.jar;C:\apache-tomcat-9.0.55\lib\catalina-ssi.jar;C:\apache-tomcat-9.0.55\lib\tomcat-coyote.jar;C:\apache-tomcat-9.0.55\lib\websocket-api.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-cs.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-de.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-es.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-fr.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-ja.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-ko.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-ru.jar;C:\apache-tomcat-9.0.55\lib\annotations-api.jar;C:\apache-tomcat-9.0.55\lib\catalina-tribes.jar;C:\apache-tomcat-9.0.55\lib\tomcat-util-scan.jar;C:\apache-tomcat-9.0.55\lib\tomcat-websocket.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-pt-BR.jar;C:\apache-tomcat-9.0.55\lib\tomcat-i18n-zh-CN.jar;C:\apache-tomcat-9.0.55\lib\catalina-storeconfig.jar, java.vm.vendor=Oracle Corporation, sun.arch.data.model=64, user.variant=, java.vendor.url=http://java.oracle.com/, user.timezone=Asia/Seoul, os.name=Windows 10, java.vm.specification.version=11, sun.java.launcher=SUN_STANDARD, user.country=KR, sun.boot.library.path=C:\jdk11\bin, sun.java.command=com.test.ch3.ApplicationContextTest, jdk.debug=release, sun.cpu.endian=little, user.home=C:\Users\back8, user.language=ko, java.specification.vendor=Oracle Corporation, java.version.date=2019-01-15, java.home=C:\jdk11, file.separator=\, java.vm.compressedOopsMode=32-bit, line.separator=
, java.specification.name=Java Platform API Specification, java.vm.specification.vendor=Oracle Corporation, java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment, user.script=, sun.management.compiler=HotSpot 64-Bit Tiered Compilers, java.runtime.version=11.0.2+9, user.name=back8, path.separator=;, os.version=10.0, java.runtime.name=OpenJDK Runtime Environment, file.encoding=x-windows-949, java.vm.name=OpenJDK 64-Bit Server VM, java.vendor.version=18.9, java.vendor.url.bug=http://bugreport.java.com/bugreport/, java.io.tmpdir=C:\Users\back8\AppData\Local\Temp\, java.version=11.0.2, user.dir=C:\java-project\ch3, os.arch=amd64, java.vm.specification.name=Java Virtual Machine Specification, java.awt.printerjob=sun.awt.windows.WPrinterJob, sun.os.patch.level=, java.library.path=C:\jdk11\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\jdk11\bin;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\iCLS\;C:\Program Files\Intel\Intel(R) Management Engine Components\iCLS\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\xampp\php;C:\composer;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\dotnet\;C:\Program Files\Microsoft VS Code\bin;C:\Program Files\MySQL\MySQL Server 8.0\bin;C:\Program Files\Git\cmd;C:\Program Files\MySQL\MySQL Shell 8.0\bin\;C:\Users\back8\AppData\Local\Microsoft\WindowsApps;C:\Users\back8\AppData\Roaming\Composer\vendor\bin;C:\Users\back8\.dotnet\tools;C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.3\bin;;., java.vendor=Oracle Corporation, java.vm.info=mixed mode, java.vm.version=11.0.2+9, sun.io.unicode.encoding=UnicodeLittle, java.class.version=55.0}
spring - annotations-api.jar
표준 - javax.inject-1.jar
스프링 애너테이션 | 표준 애너테이션 | 비고 |
@Autowired | @Inject ( x ) | 표준에는 reequired 속성 없음 |
@Qualifier | @Qualifier ( x ) , @Named ( x ) | 스프링 @Qualifier 는 @Named 와 비슷 |
X | @Resource | 스프링에선 이름검색 없음 |
@Scope("singleton") | @Singleton | 표준에서는 prototype 이 기본 |
@Component | @Named , @ManagedBean | 표준에서는 반드시 이름 필요 |
config.xml 이 setter를 이용하여 자동으로 값을 할당 할때 규칙( 빈의 초기화 - list , set , map )
===== List ( String 기본형 일때 ) =====
<property name="colors">
<list>
<value>red</value>
<value>green</value>
<value>blue</value>
</list>
</property>
===== List ( 참조형 일때 ) =====
<property name="engines">
<list>
<ref bean="superEngine" />
<ref bean="turboEngine" />
</list>
</property>
===== Set =====
<property name="engines">
<set>
<ref bean="superEngine" />
<ref bean="turboEngine" />
</set>
</property>
===== map ( 기본형 일때 ) =====
<property name="doorColors">
<map>
<entry key="left" value-ref="red" />
<entry key="right" value-ref="blue" />
</map>
</property>
===== map ( 참조형 일때 ) =====
<property name="doors">
<map>
<entry key="left" value-ref="door" />
<entry key="right" value-ref="door" />
</map>
</property>