HelloSpringApplication.class
package hello.hellospring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloSpringApplication {
public static void main(String[] args) {
SpringApplication.run(HelloSpringApplication.class, args);
}
}
controller.MemberController.class
package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
MemberService.class
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class MemberService {
private final MemberRepository memberRepository;
//MemberService입장에서 외부repository를 넣어줌 - > Dependency Injection!
@Autowired
public MemberService(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
//회원가입
public Long join(Member member){
//같은 있는 중복 회원X
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
public List<Member> findMembers(){
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId){
return memberRepository.findById(memberId);
}
}
MemoryMemberRepository.class
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member-> member.getName().equals(name))
.findAny();
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore(){
store.clear();
}
}
@Component annotation을 통해
MemberController -> MemberService -> MemoryMemberRepository 순으로
의존관계를 주입하고 있다.
cf.
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
* Indicates that an annotated class is a "Repository", originally defined by
* Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage,
* retrieval, and search behavior which emulates a collection of objects".
*
* <p>Teams implementing traditional Java EE patterns such as "Data Access Object"
* may also apply this stereotype to DAO classes, though care should be taken to
* understand the distinction between Data Access Object and DDD-style repositories
* before doing so. This annotation is a general-purpose stereotype and individual teams
* may narrow their semantics and use as appropriate.
*
* <p>A class thus annotated is eligible for Spring
* {@link org.springframework.dao.DataAccessException DataAccessException} translation
* when used in conjunction with a {@link
* org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
* PersistenceExceptionTranslationPostProcessor}. The annotated class is also clarified as
* to its role in the overall application architecture for the purpose of tooling,
* aspects, etc.
*
* <p>As of Spring 2.5, this annotation also serves as a specialization of
* {@link Component @Component}, allowing for implementation classes to be autodetected
* through classpath scanning.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 2.0
* @see Component
* @see Service
* @see org.springframework.dao.DataAccessException
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@Controller, @Service, @Repository 내부에
@Component가 포함되어 있다.