그럼 Servlet이란? 

자바엔터프라이즈 에디션에서 제공하는 웹을 만들 수 있게 제공하는것이다.

요청당 쓰레드를 사용한다.

 

지금은 직접 사용하진않지만 Spring의 기초뼈대이다.

 

서블릿은 단독으로 실행할 수 없고 서블릿 컨테이너가 실행해야한다.

 

서블릿 스펙을 준수하는 컨테이너(톰캣)가 서블릿의 라이플사이클을 이용해 실행한다.

 

라이플사이클

서블릿컨테이너가 서블릿 인스턴스의 init메소드를 호출하여 초기화한다.

 

서블릿 컨테이너가 구동될때 서블릿 리스너가 DB에 연결하고 여러가지 서블릿에 제공할 수 있다.

서블릿컨텍스트에서 꺼내서 사용한다.

 

서블릿 컨테이너가 종료할때 서블릿 리스너를 이용해 DB커넥션을 반납한다.

 

 

Java servlet API은 런타임때 빠진다. 컨테이너가 가지고있다.

 

Servlet 예제

public class HelloServlet extends HttpServlet {

    //원시적인 ServletApplication
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        ApplicationContext applicationContext = (ApplicationContext) getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

        HelloService helloService = applicationContext.getBean(HelloService.class);
        resp.getWriter().println("Hello "+ helloService.getName());
    }

    private Object getName() {
        return getServletContext().getAttribute("name");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }

    @Override
    public void init() throws ServletException {
        System.out.println("init");
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

 

서블릿에서 사용하는 두가지 기능

 

서블릿리스너

servletlistener

public class MyListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized");
        //서블릿보다 윗개념이기에 서블릿에서 꺼내서 사용할 수 있다.
        sce.getServletContext().setAttribute("name","사용");
    }

    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed");
    }
}

-서블릿 컨테이너보다 윗개념

-서블릿컨테이너에서 발생하는 이벤트에 특정한 코드를 실행할때 사용한다.

-종료될때도 사용할 수 있다.

-(DB연결등 여러가지)

 

서블릿필터

servletfilter

public class MyFilter implements Filter {
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter");
        //체인형식으로 다음필터에게 전달해주어야한다.
        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("My Filter init");
    }

    public void destroy() {
        System.out.println("My Filter destroy");
    }
}

-필터를 거쳐 서블릿에간다

-요청이 들어왔을때 서블릿으로 가기전에 전처리할때 사용한다.

-여러개의 서블리셍 추가적인 작업을 하거나 특정한 URL에 적용할 수 있다.

-체인 구조로 순차적으로 실행된다.

Autowired란?

빈에서 다른 빈의 의존성을 주입하는것이다.

즉, A bean이 B bean을 사용하려면 @Autowired해준다.

 

Autowired된 bean을 먼저 생성한다. 생각해보면 먼저 생성되어있어야 사용할 수 있다.

@Component
public class BookServiceRunner implements ApplicationRunner {

    //BookService를 사용한다.
    @Autowired
    BookService bookService;

    public void run(ApplicationArguments args) throws Exception{
        bookService.printBookRepository();
    }
}

 

기본적으로는 Autowired를 사용하면 의존성이 있어야하므로 bean으로 등록되어있어야한다.

 

필드,setter에선 (required = false) 으로 의존성을 강제하지 않을 수 있다.

필드에 사용하는것과 생성자에 사용하는건 약간다르다.

    //BookService를 사용한다.
    //의존성 강제 설정해체
    @Autowired (required = false)
    BookService bookService;

 

또 repository가 여러개일 경우 충돌이 난다. 

이럴땐 @Primary나 @Qualifier("huBookRepository")로 강제해주어야한다.

Primary형식

//Primary형식
@Repository @Primary
public class MyBookRepository implements BookRepository {
    @Override
    @PostConstruct
    public void setUp() {
        System.out.println("MyBookRepository");
    }
}

Qualifier형식

    //Qualifier형식
    @Autowired @Qualifier("myBookRepository")
    BookRepository bookRepository;

아니면 모두 사용하고 싶을 경우 LIst형식으로 받을 수 있다.

    @Autowired
    List<BookRepository> bookRepository;

LOG를 찍어보게되면 BookRepository를 implements한 클래스가 모두 나온다

@Service
public class BookService {

    @Autowired
    List<BookRepository> bookRepository;

    public void printBookRepository(){
        this.bookRepository.forEach(System.out::println);
        System.out.println(bookRepository.getClass());
    }
}

인스턴스 생성될때 동작하기 

@Repository
public class MyBookRepository extends TestExtends implements BookRepository  {
    @Override
    @PostConstruct
    public void setUp() {
        System.out.println("MyBookRepository");
    }
}

 

 

 

 

@Component와 컴포넌트 스캔

Component는 스프링 3.1부터 적용되었다.

 

@Component를 사용할 경우 IOC컨테이너에 bean으로 등록한다.

@Service,@Repository,@Controller등 여러가지 애노테이션엔

@Component가 포함되어있다.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component //Service에 등록되어있는 Component
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

ComponentScan

여러가지 bean들을 검색하고 IOC컨테이너에 적재한다.

 

스프링부트에선 @SpringBootApplication가 시작지점이 된다.

@SpringBootApplication
public class DemoApplication {

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

}

SpringBootApplication 내부 모습

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

 

@SpringBootApplication 이하의 모든 클래스가 @ComponentScan

(basePackages,basePackageClasses)에 의해 컴포넌트 스캔이된다.

 

만약 개발할때 bean주입이 안되면 컴포넌트 스캔위치를 살펴봐야한다.

모든걸 bean으로 등록하는것이 아니라 필터로 걸러낼 수 있다.

 

, 빈을 다등록하는게 부담된다면 펑션으로 특정빈만 등록할 있다.

'개발 소발 > 개발 Spring' 카테고리의 다른 글

Spring Environment 기초 사용방법  (0) 2020.07.13
Spring Scope란?  (0) 2020.07.13
AOP란? AOP 기초개념  (0) 2020.07.09
Spring IoC(Inversion of Control),Bean,의존성주입이란?  (0) 2020.07.08
프레임워크 개념  (0) 2018.01.26

AOP

Aspect(관심사)

공통된 관심사?로 이해하면 쉽다.

 

여러 클래스에서 같은 로직(관심사)이 실행될 때 사용한다.

 

공통적인 로직을 클래스에 하나하나 추가하지 않고 별도의 클래스로 생성한다.

 

예를 들어 모든 로직의 수행시간을 측정하려고 한다.

//시작

StopWatch sw = new StopWatch();

sw.start();

//여러가지 로직들

//끝

sw.stop();

System.out.println(sw.prettyPrint());

 

공통된 로직이 모두 들어간다.

 

공통된 로직을 분리 후 실행하는방법

 

-컴파일

컴파일할때 코드를 넣어준다.

 

-바이트코드 조작

A.java -> A.Class 하고 실행 시 클래스 로더가 메모리에 올릴 때 조작한다.

 

컴파일, 바이트코드 조작의 차이점 코드가 아닌 메모리에 올라간다.

두 개다 AspectJ가 지원한다.

 

-프록시패턴(스프링AOP)

인터페이스 implements를 통해 구현한다. 

한번 더 감싸는 구조로 생각하면 쉽다.

 

(

공통 로직

(실행 로직)

공통 로직

)

자동으로 bean 등록될 때 만들어진다.

 

 

애노테이션을 사용하여 AOP 적용한 예제

@LogExecutionTime을 만들어보기

@GetMapping("/owners/find")

//만들 애노테이션 명

@LogExecutionTime

public String initFindForm(Map<String, Object> model) {

model.put("owner", new Owner());

return "owners/findOwners";

}

 

구현할 애노테이션 생성

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface LogExecutionTime {

}

 

 

@Around로 ProceedingJoinPoint를 파라미터로 받는다.

ProceedingJoinPoint는 애노테이션을 설정한 타깃을 말한다.

즉 애노테이션 달려있는 메서드!

//bean으로 등록

@Component

//Aspect 설정

@Aspect

public class LogAspect {



Logger logger = LoggerFactory.getLogger(LogAspect.class);



@Around("@annotation(LogExecutionTime)")

public Object LogExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable{

StopWatch sw =new StopWatch();

sw.start();

//위애 애노테이션 달려있는 메소드 실행

Object procced= joinPoint.proceed();



sw.stop();

logger.info(sw.prettyPrint());



return procced;

}

}

 

같은 로직인데 여러 군데 들어간다면 AOP를 활용하는 게 좋다.

애노테이션을 쓰지 않는 방법도 있다.

여러 가지방법과 사용방법이 존재한다.

'개발 소발 > 개발 Spring' 카테고리의 다른 글

Spring Scope란?  (0) 2020.07.13
Spring Autowired와 ComponentScan이란  (0) 2020.07.10
Spring IoC(Inversion of Control),Bean,의존성주입이란?  (0) 2020.07.08
프레임워크 개념  (0) 2018.01.26
SpringMVC란?  (0) 2018.01.11

자바 Exception 핸들링

Exception

- 프로그램이 핸들링할 수 있는 경우를 Exception이라고 한다.

- 처리가 가능하다.

- checked exception(complie time)

+ 실행하기 이전 예측가능하다.

+ 파일 확인할때 에러,SQL관련

+ 이클립스,인텔리제이등 ide가 컴파일 할때 체크 해준다.

- unchecked exception(runtime)

+ 실행해야 알 수 있다.

+ 실행시 객체생성없는경우(NullPointer), Array싸이즈가 안맞는 에러등이 있다.

Error

- 핸들링이 불가능해 회복이 불가능하다. 대표적으로 OOM(메모리문제)가 있다.


Exception 핸들링 방법

try, catch block

- 블럭을 설정해 Exception을 처리해준다.

throws

- 메소드 선언부에서 사용한다.

- 메소드를 불러오는 메소드에 책임은 전가한다.

- Exception이 생기면 던져준다.

throw(인위적 Exception 발생)

- Exception이 필요한 상황에 개발자가 Exception을 발생시킨다.

- try, catch나 throws를 사용해야한다.

자바에서 static개념

- 객체지향프로그램인 자바는 객체,변수등이 필요할때 메모리에 올려야한다.

- static은 프로그램으로 객체생성이전 JVM에 클래스가 로딩될때 메모리에 올라온다.

- 변수,메소드,내부클래스에서 static을 사용가능하다.

- 변수,메소드에서 자주사용한다.

- 변수에 static이 붙게 되면 Class로 접근 가능하다.

- 전역변수가 필요할때 static을 사용한다.

- 메소드에 static이 붙게되면 Class로 접근가능하다.

- 대표적인예제 public static void main(String[] args)


abstract와 Interface의 차이

SuperClass와 subClass로 구성된건 같다.

서브클래스는 슈퍼클래스의 큰 영향을 받는다.


abstactClass

- 슈퍼클래스가 어느정도 구현되어있고 나머지를 서브클래스에서 구현해야할때사용한다.

- single inheritance이다.(다중상속불가능)

- 모든 접근제한자에서 가능하다.

- 일반적인 변수,상수가 사용가능하다.

- abstractMethods,concreteMethods 둘다 가능하다.


Interface

- 실질적인 구현이없는 abstractMethods만있는 빈깡통클래스

- 일종의 규약을 위해 생성한다.

- 상속이아닌 구현으로 다중구현이 가능하다.

- public만 가능하다.

- 오직 상수만이 가능하다.

- abstractMethods만가능하다.

오버라이딩

overriding

- 부모 클래스로 부터 상속받은 메소드를 자식클래스에서 다시구현한다.

- 자식클래스에서 입맛에 맞게 다시 구현

- 메소드에 파라미터,리턴타입은 부모,자식클래스이 같아야한다.

- 자식클래스에서 필요해의해 다양하게 수정하기 위해서이다.


오버로딩

overloading

- 같은 클래스안에서 이름이 같은 메소드를 말한다.

  - 이름은 같은 메소드지만 다양한 파라미터를 받아서 처리할때 사용한다.

- 파라미터가 달라야한다.

- 리턴타입은 같지않아도 된다.

String 생성 방법의 차이

1. String s1 = new String("Java");

2. String s2 = "Java"; <-리터럴방식

1번 방식으로 생성하게 되면 힙메모리에 올라가게된다.

2번 방식으로 생성하게되면 자바1.7이후 힙메모리안 StringPool이라는 특정메모리안에 올라가게된다.

2번 방식은 값이 같을 경우 같은 주소를 보게된다.


즉, == 로 비교하게되면 주소값을 비교하게되는데 2번방식으로 생성할때만 비교할 수 있다.

.equals()방식은 문자열을 비교하는 것이기 때문에 모두 가능하다.


즉, new()로 생성하면 힙메모리에 생성되고 ""로 생성하게되면 힙메모리안 StringPool에 생성되어 재사용가능하다.



String,StringBuffer,StringBuilder의 차이


String은 불가변적이다.

StringBuffer,StringBuilder은 가변적이다.


String 객체는 Heap메모리에 생성되면 변하지않는다.

변경하게되면 새로운 객체를 생성해야한다.

ex)

String s = "a";

s = s + "b";


String 는 객체(Heap메모리) s는 reference 값(Stack메모리)이다.

String s = "a";

s(reference값)은 Heap 메모리의 "a"의 주소값을 보고 있다.


s = s + "b"; 를 하게되면 

s(reference값)가 보고있는 "a"값에 "b"를 추가하는것이아닌

"ab"라는 객체를 다시만들고 그 객체의 reference값으로 바꾼다.


ex)StringBuffer ,StringBuilder 동일하다.

StringBuffer s = new StringBuffer("a");

s.append("b");


StringBuilder,StringBuffer 는 객체(Heap메모리) s는 reference 값(Stack메모리)이다.

차이점은 StringBuilder,StringBuffer는 객체를 새로 생성하지않고

기존 객체에 값을 추가한다.


개발시에 문자열 병합이 빈번하게 일어나면 StringBuilder,StringBuffer를 사용하는게 좋다.


StringBuilder,StringBuffer 차이는?


synchronization(동기화)지원여부의 차이다.


synchronization란?

하나에 제한되어있는 데이터를 여러 스레드가 공유가 사용할때

데이터가 깨지지않게 줄을세워 키를 가지고 있는 데이터를 처리하고 나머지데이터는 대기시킨다.

데이터무결성을 보장할 수 있다.


StringBuffer는 동기화를 지원하고

StringBuilder는 동기화를 지원하지 않는다.


멀티스레드를 사용하지 않는다면 

StringBuffer보단 StringBuilder가 빠르다.


자바 메모리영역 Stack,Heap


Stack

- Stack 메모리는 비교적 가벼운데이터들을 말한다.

- primativeData,reference(주소값)이 있다.


Heap

- Heap 메모리는 객체등 무거운데이터가 머물러있다.

- Garbage Collection은 Heap메모리에서 작동한다.


ex)

마트에 갔을때 가벼운 물건들은 바로바로 구매하지만

배송이 필요한 물건은 reference를 보고 구매하면

Heap에서 가져오게 된다.

autoboxing,unboxing이란?


autoboxing,unboxing의 개념은 jdk 1.5 부터 나왔다.


자바에는 크게 2가지 데이터 타입이 있다.

primitive Data,Object Data 두가지!


primitive Data

- boolean, char, byte, short, int, long, float, double

- 아주 가벼운 데이터를 말한다.

- 스택메모리에 머물러있다.


Object Data

- 상대적으로 무거운 데이터이다.

- 실제 데이터는 힙메모리에 공유하고 레퍼런스만 스택메모리에 있다.


Wrapper Class

- primitive Data를 ObjectData화 시킨 Class이다.


jdk 1.5 이전에 서로 호환할려면 개발자가 명시적으로 바꿔줬어야했다.

하지만 jdk 1.5가 나오면서 직접호환이 가능하게 되었다.


primitive Data 에서 Wrapper Class로 자동으로 변환되는걸 autoboxing이라 한다.

가벼운 데이터를 무거운데이터에 넣기에 autoboxing이라고 생각하면 간단하다.


Wrapper Class에서 primitive Data 자동으로 변환되는걸 unboxing이라 한다.

무거운 데이터를 가벼운데이터에 넣기에 unboxing이라고 생각하면 간단하다.


autoboxing이란?

- 컴파일러가 primitive Data를 Object Data로 자동변환하는것이다.

- int a = 42; Integer b =a;

- 과거엔 객체를 생성했어야했다.


unboxing이란?

- 컴파일러가 Object Data를 primitiveData로 자동변환하는것이다.

- Integer a = new Integer(42); int b =a;

- 과거엔 a.intValue();로 생성했어야했다.


+ Recent posts