AOP(Aspect Oriented Programming) - 인강

Back-End/Spring 2019. 6. 5. 00:07
728x90
반응형

AOP(Aspect Oriented Programming)


핵심 : 흩어진 코드를 한 곳으로 모아서 코딩


 

 -흩어진 코드-


 class A {    

method a ( ) {            

    AAAA            

    오늘은 7월 4일 미국 독립 기념일이래요.            

    BBBB    

 }      


 method b ( ) {            

    AAAA            

    저는 아침에 운동을 다녀와서 밥먹고 빨래를 했습니다.            

    BBBB    

 }


 class B {   

 method c( ) {           

    AAAA           

    점심은 이거 찍느라 못먹었는데 저녁엔 제육볶음을 먹고 싶네요.              BBBB   

 }





  

 -모아 놓은 AAAA 와 BBBB-


 class A {    

 method a ( ) {            

오늘은 7월 4일 미국 독립 기념일이래요.    

 }      


 method b ( ) {            

저는 아침에 운동을 다녀와서 밥먹고 빨래를 했습니다.    

    } 

 }

  

 class B {   

 method c( ) {           

점심은 이거 찍느라 못먹었는데 저녁엔 제육볶음을 먹고 싶네요.   

    } 

 }


 class AAAABBBB {     

method aaaabbb (JoinPoint point) {          

AAAA   

point.execute( )          

BBBB 

    } 

 }

 



바이트 코드를 조작하는 방법


컴파일 하면 닷(.) 클래스 파일이 생기는데 이 클래스 파일을 조작하는 것

이미 컴파일된 코드 안에 끼워넣는것 AAAA와 BBBB를....




프록시 패턴을 사용하는 방법 (스프링 AOP에서 사용하는 방법!!!!)


A라는 클래스 타입의 객체를 상속을 받아 A-클래스를 만들고, a( ) 메소드 호출후

AAAA라고 나오게끔 하고, b( ) 메소드 호출후 BBBB라고 출력하게함.



 

  프록시 패턴(proxy pattern)은 컴퓨터 프로그래밍에서 소프트웨어 디자인 패턴의 하나이다.

  일반적으로 프록시는 다른 무언가와 이어지는 인터페이스의 역할을 하는 클래스이다. 프록시는 어떠한 것(이를테면 네트워크 연결, 

  메모리 안의 커다란 객체, 파일, 또 복제할 수 없거나 수요가 많은 리소스)과도 인터페이스의 역할을 수행할 수 있다.

  




트랜잭션 처리 예제


 

class A {    

method a ( ) {            

    AAAA                                                // 트랜잭션 매니저를 가지고 트랜잭션을 오토커밋을 false로 하고 밑에 구문 실행          

    오늘은 7월 4일 미국 독립 기념일이래요.   //이 구문은 try~catch로 묶어놓음, catch블럭에서 문제가 생겼을 경우 롤백시킴 

BBBB //그 코드가 AAAA, BBBB처럼 모든코드를 감싼다 

                                                        //오늘은~ 실행하고 커밋을 하면 트랜잭션 처리가 된다.

 }      





OwnerController (컨트롤러)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@Controller
class OwnerController {
 
    private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
    private final OwnerRepository owners;
 
 
    public OwnerController(OwnerRepository clinicService) {
        this.owners = clinicService;
    }
 
    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("id");
    }
 
    @LogExecutionTime
    @GetMapping("/owners/new")
    public String initCreationForm(Map<String, Object> model) {
        Owner owner = new Owner();
        model.put("owner", owner);
        return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
    }
    @LogExecutionTime
    @PostMapping("/owners/new")
    public String processCreationForm(@Valid Owner owner, BindingResult result) {
        if (result.hasErrors()) {
            return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
        } else {
            this.owners.save(owner);
            return "redirect:/owners/" + owner.getId();
        }
    }
    @LogExecutionTime
    @GetMapping("/owners/find")
    public String initFindForm(Map<String, Object> model) {
        model.put("owner"new Owner());
        return "owners/findOwners";
    }
    @LogExecutionTime
    @GetMapping("/owners")
    public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {
 
        // allow parameterless GET request for /owners to return all records
        if (owner.getLastName() == null) {
            owner.setLastName(""); // empty string signifies broadest possible search
        }
 
        // find owners by last name
        Collection<Owner> results = this.owners.findByLastName(owner.getLastName());
        if (results.isEmpty()) {
            // no owners found
            result.rejectValue("lastName""notFound""not found");
            return "owners/findOwners";
        } else if (results.size() == 1) {
            // 1 owner found
            owner = results.iterator().next();
            return "redirect:/owners/" + owner.getId();
        } else {
            // multiple owners found
            model.put("selections", results);
            return "owners/ownersList";
        }
    }
cs

SampleController (컨트롤러)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
public class SampleController {
 
    @Autowired
    String keesun;
 
 
    @LogExecutionTime //아래 구문이 실행되는게 얼마나걸리는지??
    @GetMapping("/context")
    public String context() {
 
        return "hello" + keesun;
    }
}
 
cs


어노테이션만있으면 주석과 같은 기능을 하므로 어노테이션을 처리할 파일을 만들어주어야 한다.
트랜잭션 처리를 어노테이션 하나로 처리할수 있어서 효율적이다.

Logaspect.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package org.springframework.samples.petclinic.aspect;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
 
@Component
@Aspect
public class Logaspect {
 
    Logger logger = LoggerFactory.getLogger(Logaspect.class); //이 클래스에서 얻는 로그를 logger변수에 저장
 
    @Around("@annotation(LogExecutionTime)")
    public Object logExcutionTime(ProceedingJoinPoint joinPoint) throws Throwable
    //스프링이 제공하는 스톱워치를 사용
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
 
        Object ret =  joinPoint.proceed();
 
        stopWatch.stop();
        logger.info(stopWatch.prettyPrint());
 
        return ret;
 
}
 
cs


728x90
반응형

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

스프링 로그 분석  (0) 2019.06.05
Oracle와 mybatis 연동 실습  (0) 2019.06.05
스프링 프로젝트 구조  (0) 2019.06.04
스프링 프레임워크 Inversion of Control (IoC)  (0) 2019.06.03
스프링 프로젝트 살펴보기  (0) 2019.06.02
: