728x90

전략 패턴의 구조에서는

클라이언트는 add, delete 같은 메서드에 해당하고

전략은 익명 내부 클래스에 해당하며

jdbcContextWithStatementStrategy 메서드를 컨텍스트라고 볼 수 있다.

 

여기서 컨텍스트는 User의 DAO에서만 사용하는 것이 아니라

다른 DAO에서도 공통적으로 사용할 수 있는 기능에 해당하기 때문에

해당 컨텍스트를 모든 DAO에서 사용할 수 있게

별도의 클래스로 독립시키는 것이 좋다.

 

클래스 분리하기

별도의 클래스를 만들어 컨텍스트 메서드를 옮기고 DI를 알맞게 설정해준다.

public class JdbcContext {
	DataSource dataSource;
	
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	
	public void workWithStatementStrategy(StatementStrategy stmt) throws SQLException {
		Connection c = null;
		PreparedStatement ps = null;

		try {
			c = dataSource.getConnection();

			ps = stmt.makePreparedStatement(c);
		
			ps.executeUpdate();
		} catch (SQLException e) {
			throw e;
		} finally {
			if (ps != null) { try { ps.close(); } catch (SQLException e) {} }
			if (c != null) { try {c.close(); } catch (SQLException e) {} }
		}
	}
}

DAO 클래스에서 해당 컨텍스트 클래스를 DI 받아서 사용할 수 있게 한다.

public class UserDao {
    private JdbcContext jdbcContext;
		
	public void setJdbcContext(JdbcContext jdbcContext) {
		this.jdbcContext = new JdbcContext();
	}
    // 생략
}

빈 의존관계 변경하기

스프링의 의존관계 주입은 기본적으로 인터페이스를 사이에 두고 의존 클래스를

상황에 맞게 유연하게 바꿔서 사용할 수 있게 하는 것이 목적이지만

JdbcContext 클래스 같이 바뀔 일이 없는 클래스는 굳이 인터페이스를 구현하여

의존관계를 주입해줄 필요는 없다.

인터페이스를 사용하지 않는 DI 적용

코드에 따라 문제가 될 수도 있고 안될 수도 있지만

JdbcContext 같은 경우는 문제가 되지 않는 정상적인 DI 방식을 적용했다고 볼 수 있다.

 

여러가지 이유가 있는데 첫 번째로는 

JdbcContext는 그저 컨텍스트 메서드를 제공하는 서비스 오브젝트로서의 의미만 있고

오브젝트 자체가 빈으로 등록되어 싱글톤으로 공유되어 사용되는 것이 이상적이다.

 

두 번째는 JdbcContext가 DI를 통해 DataSource라는 빈에 의존하고 있기 때문인데

스프링의 DI를 위해서는 주입되는 쪽과 주입받는 쪽이 모두 빈으로 등록되야 하기 때문이다.

코드를 이용하는 수동 DI

DAO 클래스 내부에서 직접 DI를 적용하는 방법인데, 이 방법을 사용하면

JdbcContext를 싱글톤으로 만드는 것은 불가능하다.

 

그렇다고 계속해서 JdbcContext 오브젝트를 생성하는 것은 아니고

DAO 오브젝트마다 하나의 JdbcContext 오브젝트를 공유하게 한다.

 

하지만 위에서 살펴봤듯이 컨테이너를 통해 DI를 받으려면

양쪽 모두 스프링 빈으로 등록이 되어있어야 하는데 이 방법을 사용하면

JdbcContext는 빈으로 등록이 되었지 않기 때문에 DataSource를 주입받을 수 없다.

 

이러한 문제를 해결하기 위해서는 DAO에 JdbcContext의 DI까지 맡기면 된다.

즉, JdbcContext아 DI 받아야 할 DataSource를 DAO가 대신 DI를 받는다.

public class UserDao {
	private DataSource dataSource;
		
    public void setDataSource(DataSource dataSource) {
        this.jdbcContext = new JdbcContext();
        this.jdbcContext.setDataSource(dataSource);

        this.dataSource = dataSource;
    }

    private JdbcContext jdbcContext;
}

이렇게 JdbcContext 대신 DataSource를 DI 받는다.

'Back-End > Spring' 카테고리의 다른 글

JDBC Template  (0) 2023.06.13
템플릿과 콜백  (0) 2023.06.13
전략 패턴 최적화 하기  (0) 2023.06.13
템플릿 적용하기  (0) 2023.06.13
스프링에 테스트 적용하기  (0) 2023.06.08

+ Recent posts