public class UserDao {
public void add(User user) throws Exception {
Connection c = DriverManager.getConnection(...);
PreparedStatement ps = c.prepareStatement(...);
ps.executeUpdate();
ps.close();
c.close();
}
public void get(String id) throws Exception {
Connection c = DriverManager.getConnection(...);
...
}
}
위의 코드는 치명적인 문제점들이 있다.
위와 같은 문제를 해결하기 위해 각 역할을 나눠야한다!
public abstract class UserDao {
protected abstract Connection getConnection();
}
public class NUserDao extends UserDao {
protected Connection getConnection() {
return DriverManager.getConnection(...);
}
}
그래서 더 좋은 방식을 쓰기 위해 상속 대신 인터페이스를 사용한다!
public interface ConnectionMaker {
Connection makeConenction();
}
인터페이스로 분리하고
public class DConnectionMaker implements ConectionMaker {
public Connection makeConnection() {
return DriverManager.getConnection(...);
}
}
위와 같이 구현
public class UserDao {
private ConnectionMaker connectionMaker;
public UserDao(ConnectionMaker connectionMaker) {
this.connectionMaker = connectionMaker;
}
}
→ 이렇게 작성하면 UserDao는 구현이 아닌, 인터페이스에 의존할 수 있게 된다
그런데, ConnectionMaker를 누가 넣어주게 될까?
UserDao dao = new UserDao(new DConnectionMaker());
→ 객체가 직접 생성하지 않고, 외부에서 넣어준다
public class DaoFactory {
public UserDao userDao() {
return new UserDao(new DConnectionMaker());
}
}
팩토리를 통해 “객체 생성”과 “사용”을 분리시킨다
기존에는 개발자가 직접 객체를 생성했다면,
이제는 팩토리가 대신 생성하게 시킨다. 즉, 객체의 생성/관리 권한이 외부로 넘어간다!
이러한 개념을 자동으로 해주는게 바로, “스프링 컨테이너”다!
스프링은 “객체 생성”, “의존관계 주입”, “라이프사이클 관리” 의 역할을 수행한다.