이전 1~2 까지는 Properties 객체를 통해서 config.xml 파일을 읽어와서
Map에 (K,V) 값으로 객체를 저장한 것을 getBean(String key) 또는 getBean(Class clazz) 를 통해서
가지고 와서 사용했는데
이번에는 @Component를 통해서 Map에 (K , V) 로 저장해 보도록 하겠다. 또한 Map에 저장된 객체를 통해서
해당 @Autowied / @Resource가 붙은 객체에 자동으로 주입해보도록 하겠다.
>>> 1. @Component 를 통해서 Map에 객체 저장하기
-- 아래의 코드중에 doComponentScan() 함수를 집중적으로 보자면
-- ClassPath를 통해서 ClassLoader를 받아서 해당 패키지 내의 모든 클래스를 Set에 저장한 후
-- 저장된 Class를 for문을 통해서 한개씩 돌리면서 @Component 어노테이션이 붙은지 확인 한 후
-- @Component 가 붙은것만 객체를 생성하여 Map에 저장하도록 하였다.
@Component
class WoodHouse extends House{}
@Component
class BrickHouse extends House{}
@Component
class Window{}
@Component
class Floor{}
class Ditest4
{
Map map;
public DiTest4() throws Exception{
map = new HashMap();
doComponentSacn();
for(Object s : map.keySet()){
System.out.println((String)s + "<<-- @Component 붙여서 저장된 객체들");
}
}
private void doComponentSacn() throws Exception{
try {
ClassLoader classLoader = DiTest4.class.getClassLoader();
ClassPath classpath = ClassPath.from(classLoader);
//패키지 내의 클래스를 다 저장.
Set<ClassPath.ClassInfo> set = classpath.getTopLevelClasses("com.fastcampus.ch3.testDi4");
// 저장된 클래스 중에 Component 어노테이션이 있는지 확인
for(ClassPath.ClassInfo classInfo : set){
Class clazz = classInfo.load();
Component component = (Component) clazz.getAnnotation(Component.class);
//@Component가 있다면 객체를 생성하여 map에 저장
if(component!=null){
String id = StringUtils.uncapitalize(classInfo.getSimpleName());
map.put(id,clazz.newInstance());
}
}
} catch(Exception e){
e.printStackTrace();
}
}
>> @Component를 통해서 Map에 저장된 객체를 나타낸 결과이다.
2. Map에 저장된 객체를 통해서 해당 @Autowied / @Resource가 붙은 객체에 자동으로 주입해보도록 하겠다.
그러기 전에 앞서.
>> House Class에 매개변수로 Window, Floor 가 있다고 할때 해당 클래스에 객체를 주입해주려면
class House{
Window window;
Floor floor;
@Override
public String toString() {
return "House{" +
"window=" + window +
", floor=" + floor +
'}';
}
}
>> house.window = window
>> house.floor = floor 를 통해서 수동으로 객체를 주입해줘야 한다.
만약에 사용하는 멤버변수에 사용자객체가 많이 있다면 일일이 주입을 해줘야 하는 불편함이 있을텐데 이를 자동으로 주입하도록 하는 로직을 한번 알아보자
이번에는
doAutoWired() , doResource() 함수를 집중적으로 확인해보자
@Component
class House{
@Autowired //@Resource
Window window;
@Autowired //@Resource
Floor floor;
@Override
public String toString() {
return "House{" +
"window=" + window +
", floor=" + floor +
'}';
}
}
@Component
class WoodHouse extends House{}
@Component
class BrickHouse extends House{}
@Component
class Window{}
@Component
class Floor{}
public class DiTest4 {
Map map;
public DiTest4() throws Exception{
map = new HashMap();
doComponentSacn();
doAutoWired();
doResource();
for(Object s : map.keySet()){
System.out.println((String)s + "<<-- @Component 붙여서 저장된 객체들");
}
}
private void doResource() {
try {
for(Object bean : map.values()){
for(Field fld : bean.getClass().getDeclaredFields()){
if(fld.getAnnotation(Resource.class)!=null){
fld.set(bean,getBean(fld.getName()));
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void doAutoWired() {
try {
for(Object bean : map.values()){
for(Field fld : bean.getClass().getDeclaredFields()){
if(fld.getAnnotation(Autowired.class)!=null){
fld.set(bean,getBean(fld.getType()));
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void doComponentSacn() throws Exception{
try {
ClassLoader classLoader = DiTest4.class.getClassLoader();
ClassPath classpath = ClassPath.from(classLoader);
//패키지 내의 클래스를 다 저장.
Set<ClassPath.ClassInfo> set = classpath.getTopLevelClasses("com.fastcampus.ch3.testDi4");
// 저장된 클래스 중에 Component 어노테이션이 있는지 확인
for(ClassPath.ClassInfo classInfo : set){
Class clazz = classInfo.load();
Component component = (Component) clazz.getAnnotation(Component.class);
//@Component가 있다면 객체를 생성하여 map에 저장
if(component!=null){
String id = StringUtils.uncapitalize(classInfo.getSimpleName());
map.put(id,clazz.newInstance());
}
}
} catch(Exception e){
e.printStackTrace();
}
}
Object getBean(String key){
return map.get(key);
}
Object getBean(Class clazz){
for(Object obj : map.values()){
if(clazz.isInstance(obj)){
return obj;
}
}
return null;
}
public static void main(String[] args) throws Exception {
DiTest4 d = new DiTest4();
House house = (House)d.getBean("house");
Window window = (Window)d.getBean("window");
Floor floor = (Floor)d.getBean("floor");
//수동으로 객체를 주입해준다.
//house.window = window;
//house.floor = floor;
System.out.println("house = " + house);
System.out.println("window = " + window);
System.out.println("floor = " + floor);
}
}
>> doResource(), doAutoWried() 코드가 둘다 유사해보인다.
>> map에 저장되어 있는 객체들중 하나를 꺼내서 getDeclaredFields() 를 통해서 해당 클래스의 모든 필드에 접근 할 수 있는 권한을 얻은 fld를 얻게 되고, 해당 fld를 통해서 Autowired.class 어노테이션이 붙은 클래스인지 확인 할 수 있다.
이때 Autowired 어노테이션이 붙어있다면 해당 객체에 해당 타입의 객체(Bean)을 주입해준다.
>> 두개의 차이점은 fld.set(bean, getBean(fld.getType() // fld.getName()); 의 차이 인데.
>> @Autowired의 경우는 By Type 으로 Map에서 Value(객체/타입) 값을 가지고 해당 Bean을 찾아서 대입해주고,
>> @Resource의 경우는By Name 으로 Map에서 Key 값을 가지고 해당 Bean을 찾아서 대입해준다.
private void doAutoWired() {
try {
for(Object bean : map.values()){
for(Field fld : bean.getClass().getDeclaredFields()){
if(fld.getAnnotation(Autowired.class)!=null){
fld.set(bean,getBean(fld.getType()));
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private void doResource() {
try {
for(Object bean : map.values()){
for(Field fld : bean.getClass().getDeclaredFields()){
if(fld.getAnnotation(Resource.class)!=null){
fld.set(bean,getBean(fld.getName()));
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
'dev > Spring' 카테고리의 다른 글
[Spring] Transaction, Commit, Rollback (0) | 2022.07.06 |
---|---|
[Spring] Di 따라하기 4 (0) | 2022.06.22 |
[Spring] Di 따라하기 2 (0) | 2022.06.22 |
[Spring] Di 따라하기 1 (0) | 2022.06.22 |
[Spring] Export / Import (0) | 2022.06.20 |