programing

@Service 주석은 어디에 보관해야 합니까?인터페이스 또는 구현?

batch 2023. 3. 7. 21:11
반응형

@Service 주석은 어디에 보관해야 합니까?인터페이스 또는 구현?

저는 스프링을 이용한 어플리케이션을 개발하고 있습니다.를 사용할 필요가 있습니다.@Service있다ServiceI ★★★★★★★★★★★★★★★★★」ServiceImplServiceImpl implements ServiceI@Service석입니니다다

을 붙여야 ?@Service이 두 가지 접근법의 차이점은 무엇입니까?

는 절대 put put를 넣지 않는다.@Component (오류)@Service인터페이스를 사용할 수 없게 되기 때문에, 인터페이스상에서, ...)를 참조해 주세요.이유를 설명하겠습니다.

클레임 1: 인터페이스가 있는 경우 해당 인터페이스를 주입점 유형으로 사용합니다.

주장 2: 인터페이스의 목적은 여러 구현에 의해 구현될 수 있는 계약을 정의하는 것입니다.다른 쪽에는 주입 지점이 있습니다.@Autowired인터페이스를 1개만 실장하고 클래스를 1개만 실장하는 것은 (IMHO) 무용지물이며 YAGNI에 위반됩니다.

팩트: 다음 내용을 입력했을 때:

  • @Component (오류)@Service ...)로 ...)로, ...)
  • 여러 클래스가 구현되어 있습니다.
  • 적어도 두 개의 클래스가 봄콩이 되고,
  • 유형 기반 주입을 위한 인터페이스를 사용하는 주입 지점이 있습니다.

'와'를 수 있습니다.NoUniqueBeanDefinitionException Profiles Qualifiers를 ) ('환경', '', '수식자' 등)

결론:사용하시는 경우@Component (오류)@Service인터페이스에서는, 2개의 클레인 중 적어도1개를 위반할 필요가 있습니다.따라서 (몇 가지 드문 시나리오를 제외하고) 이 방법은 유용하지 않다고 생각합니다.@Component인터인스스하하하


Spring-Data-JPA Repository 인터페이스는 전혀 다릅니다.

기본적으로 @Service, @Repository, @Component 등의 주석은 모두 동일한 목적을 수행합니다.

주석 기반 구성 및 클래스 경로 스캔을 사용할 때 자동 수정됩니다.

내 경험상 나는 항상 사용하고 있다.@Service에 또는 및 과 같은 주석@Component ★★★★★★★★★★★★★★★★★」@Repository구현에 도움이 됩니다. @Component기본적인 목적을 제공하는 수업에서 사용하는 주석, 단순한 스프링 원두, 그 이상도 이하도 아닙니다. @Repository에서 하고 있는 DAO예를 들어 데이터베이스와 통신해야 하는 경우, 일부 트랜잭션 등이 있습니다.

저는 에 주석을 붙이는 것을 합니다.@Service기능에 따라 다른 레이어에도 대응합니다.

하였습니다.@Component,@Service,@Controller ★★★★★★★★★★★★★★★★★」@Repository인터페이스에서는 주석 없이 구현 클래스에서만 주석을 달 수 있습니다. ★★★★★★★★★★★★★★★★★.@Autowired인터페이스를 사용한 주석도 여전히 유효했습니다.인 경우 은 1개의 인터페이스만 됩니다.@Autowired 여러 가지이 있는 구현합니다.@Qualifier with annot annot along annot annotation@Autowired이치노

1. @인터페이스상의 서비스

@Service
public interface AuthenticationService {

    boolean authenticate(String username, String password);
}

보통은 괜찮지만 단점이 있어요.s Spring's를 .@Service인터페이스에서는, 한층 더 의존성을 만들어, 인터페이스를 외부 라이브러리와 결합합니다.

새로운 서비스 원두의 AuthenticationService:

public class InMemoryAuthenticationService implements AuthenticationService {

    @Override
    public boolean authenticate(String username, String password) {
        //...
    }
}

도입하는 '신규 도입'이라는해야 합니다.InMemoryAuthenticationServicedoesn,가 없습니다@Service석을을달달달달달@Service에서만, 「」를 참조해 주세요.AuthenticationService.

기본적인 Spring Boot 설정을 사용하여 Spring 컨텍스트를 실행합니다.

@SpringBootApplication
public class AuthApplication {

    @Autowired
    private AuthenticationService authService;

    public static void main(String[] args) {
        SpringApplication.run(AuthApplication.class, args);
    }
}

앱을 실행하면 악명 높은 NoSch Bean Definition이 나타날 수 있습니다.예외로 스프링 컨텍스트가 시작되지 않습니다.

「」, 「」를 배치한다.@Service합니다.


2. @Abstract 클래스 서비스

「 」의 @Service추상 수업에 대한 주석은 흔하지 않습니다.

하고, 를 붙이는 @Service★★★★

@Service
public abstract class AbstractAuthenticationService {

    public boolean authenticate(String username, String password) {
        return false;
    }
}

다음, 하다, 하다, 하다를 펼칩니다.AbstractAuthenticationService주석을 달지 않고 구체적인 구현을 작성하려면:

public class LdapAuthenticationService extends AbstractAuthenticationService {

    @Override
    public boolean authenticate(String username, String password) { 
        //...
    }
}

에 따라 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★AuthApplication'CHANGE: 'CHANGE: 'CHANGE: 'CHANGE: 'CHANGE:

@SpringBootApplication
public class AuthApplication {

    @Autowired
    private AbstractAuthenticationService authService;

    public static void main(String[] args) {
        SpringApplication.run(AuthApplication.class, args);
    }
}

★★★★를 한 후AuthApplicationSpring 컨텍스트가 시작되지 않습니다.같은 No Such Bean Definition으로 끝납니다.예외가 다시 발생했습니다.

이렇게 so,를 사용해서 so so so를 사용해서@Service봄에는 추상 수업에 대한 주석이 아무런 영향을 미치지 않습니다.


3. @콘크리트 클래스에서의 서비스

앞에서 설명한 것과 달리 추상 클래스나 인터페이스 대신 구현 클래스에 주석을 다는 것은 매우 일반적인 방법입니다.

이 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 가을, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄, 봄@Component해 주세요.@Service저희 같은 경우에는요.

따라서 Spring은 클래스 경로에서 이러한 클래스를 자동 검출하고 자동으로 관리 대상 빈으로 정의합니다.

그럼 ★★★★★★★★★★★★★★」@Service★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★인터페이스를 구현하는 클래스와 이전에 정의한 추상 클래스를 확장하는 클래스가 있습니다.

@Service
public class InMemoryAuthenticationService implements AuthenticationService {

    @Override
    public boolean authenticate(String username, String password) {
        //...
    }
}

@Service
public class LdapAuthenticationService extends AbstractAuthenticationService {

    @Override
    public boolean authenticate(String username, String password) {
        //...
    }
}

서 해야 할 의 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.AbstractAuthenticationService 경우, 을 하지 않습니다.AuthenticationService그래서 우리는 그것들을 독립적으로 테스트할 수 있습니다.

두 를 모두 ""에 합니다.AuthApplication번 해보겠습니다.

@SpringBootApplication
public class AuthApplication {

    @Autowired
    private AuthenticationService inMemoryAuthService;

    @Autowired
    private AbstractAuthenticationService ldapAuthService;

    public static void main(String[] args) {
        SpringApplication.run(AuthApplication.class, args);
    }
}

최종 테스트 결과 Spring 컨텍스트는 예외 없이 부팅됩니다.두 서비스 모두 자동으로 콩으로 등록됩니다.

다른 설명은 이 페이지를 참조해 주십시오.

@Service에 주석을 다는 장점은 서비스라는 힌트를 준다는 것입니다.구현 클래스가 기본적으로 이 연결을 상속할지 알 수 없습니다.

단점은 인터페이스를 특정 프레임워크와 결합하는 것입니다.스프링(스프링별 주석을 사용).인터페이스는 구현에서 분리되어야 하므로 프레임워크 고유의 주석이나 인터페이스의 객체 부분을 사용하는 것은 권장하지 않습니다.

@Service인터페이스 이름을 주석에 파라미터로 지정합니다.

interface ServiceOne {}

@Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}

이를 통해 모든 이점을 얻을 수 있고 인터페이스를 주입할 수 있지만 클래스는 얻을 수 있습니다.

@Autowired 
private ServiceOne serviceOne;

따라서 인터페이스는 스프링 프레임워크에 얽매이지 않고 언제든지 클래스를 변경할 수 있으며 모든 주입 지점을 업데이트할 필요가 없습니다.

구현 클래스를 변경하려면 새 클래스에 주석을 달아 첫 번째 클래스에서 삭제하기만 하면 됩니다. 변경은 이것뿐입니다.만약 당신이 수업을 주입한다면, 당신은 언제나 당신이 임팩트 수업을 바꾸고 싶을 때 많은 일을 할 수 있을 것입니다.

봄의 장점 중 하나는 서비스(또는 기타) 구현을 쉽게 전환할 수 있다는 것입니다.이를 위해서는 다음과 같이 인터페이스에 주석을 달아 변수를 선언해야 합니다.

@Autowired
private MyInterface myVariable;

다음 중 하나가 아닙니다.

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

첫 번째 경우와 마찬가지로 어떤 실장이 고유한 시점부터 어떤 실장을 활성화 할 수 있습니다(인터페이스를 실장하는 클래스는 1개뿐입니다).두 번째 경우 모든 코드를 리팩터링해야 합니다(새 클래스 구현에는 다른 이름이 있습니다).따라서 주석은 가능한 한 인터페이스에 있어야 합니다.또한 JDK 프록시는 응용 프로그램 부팅 시 생성 및 인스턴스화되므로 CGlib 프록시와 달리 런타임 유형이 미리 알려져 있습니다.

interface MyService {}

@Service
class MyServiceImpl implements MyService{}

@Autowired 
private MyService myService;

스프링 부트 2.7.4에서의 테스트 결과는 다음과 같습니다.

인터페이스에 @Service ONLY를 추가해도 MyService라는 이름의 spring bean은 생성되지 않습니다.자동 전원으로 에러가 발생합니다.

@를 구현 하여 bean @을 작성해야 com.*.service.impl.MyServiceImpl $$EnhancerBySpringCGLIB$$9140ae19Spring MyService MyService spring spring spring spring spring 。

봄콩을 만들 때 사용할 수 있는 주석은 5개입니다.아래에 답을 나열하십시오.

인터페이스가 정말 필요합니까?각 서비스 인터페이스에 대해1개의 실장을 실시하는 경우는, 회피하고, 클래스만을 사용합니다.물론 RMI가 없거나 인터페이스 프록시가 필요한 경우입니다.

@Repository - dao 레이어 클래스를 주입하기 위해 사용합니다.

@Service - 서비스 계층 클래스를 주입하기 위해 사용합니다.서비스 계층에서는 DB 트랜잭션 관리를 위해 @Transactional 주석을 사용해야 할 수도 있습니다.

@Controller - 스프링 콩으로 주입하는 JSF 관리 콩 등 프론트 엔드 레이어 컨트롤러에 사용합니다.

@RestController - 스프링레스트 컨트롤러에 사용하면 @ResponseBody 및 @RequestBody 주석을 rest 메서드에 추가할 때마다 이를 피할 수 있습니다.

@Component - 컨트롤러, 서비스, dao 클래스가 아닌 스프링빈을 주입해야 할 때 사용합니다.

간단히 말하면:

@Service서비스 계층의 고정관념 주석입니다.

@Repos(반복)는 퍼시스텐스 층에 대한 고정관념 주석입니다.

@Component는 Application Context에서 객체의 인스턴스를 생성하도록 Spring에게 지시하기 위해 사용되는 일반적인 고정관념 주석입니다.인스턴스 이름을 정의할 수 있습니다.기본값은 camel 대소문자로 클래스 이름입니다.

언급URL : https://stackoverflow.com/questions/16351780/where-should-service-annotation-be-kept-interface-or-implementation

반응형