'개발관련/Spring'에 해당되는 글 15건

  1. 2015.12.04 :: hibernate(3)
  2. 2015.12.04 :: hibernate(2)
  3. 2015.12.04 :: hibernate(1)
  4. 2015.11.30 :: aop(2)
  5. 2015.11.30 :: AOP(1)
개발관련/Spring 2015. 12. 4. 14:29

하나의 객체에 두개의 테이블 생성하기 를 해보자. 


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
package com.zest.hibernate.chapter2;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
 
 
@Entity
@Table(name="Customer")
@SecondaryTable(name="CustomerDetail")
public class Customer {
 
    
    @Id
    @GeneratedValue
    private int customerId;
    private String customerName;
    
    @Column(table="CustomerDetail")
    private String customerAddress;
    
    @Column(table="CustomerDetail")
    private int creditScore;
    @Column(table="CustomerDetail")
    private int rewardPoints;
    
    public int getCustomerId() {
        return customerId;
    }
    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }
    public String getCustomerName() {
        return customerName;
    }
    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }
    public String getCustomerAddress() {
        return customerAddress;
    }
    public void setCustomerAddress(String customerAddress) {
        this.customerAddress = customerAddress;
    }
    public int getCreditScore() {
        return creditScore;
    }
    public void setCreditScore(int creditScore) {
        this.creditScore = creditScore;
    }
    public int getRewardPoints() {
        return rewardPoints;
    }
    public void setRewardPoints(int rewardPoints) {
        this.rewardPoints = rewardPoints;
    }
    
    
    
}
 
cs


처음 보는 어노테이션이 등장한다. @SecondaryTable 이라는 넘이다. 기존 customer 말고 cumstomerDetail 이라는 테이블로 선언이 되었다. 이 객체의 재미난 점은 기본키는 둘다 같은 column을 사용한다는 것이다. 그리고 detail의 경우 cumstomerId를 기본키로 하면서 외래키를 가진다.  그리고 sencondaryTable에 추가할 컬럼은 @Column 어노테이션을 사용하여 추가한다. 


아마도 1:1 대응 구조에 사용하면 좋을듯 보인다. 그럼 테스트 코드를 보자. 

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
 
package com.zest.hibernate.chapter2;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;
 
public class CustomerTest {
 
    @Test
    public void customer1() {
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Customer.class);
        config.configure("hibernate.cfg.xml");
 
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
 
        Customer alex = new Customer();
        alex.setCustomerName("Alex Rod");
        alex.setCustomerAddress("101 washington");
        alex.setCreditScore(780);
        alex.setRewardPoints(12000);
        
        session.save(alex);
        session.getTransaction().commit();
    }
}
 
cs



사용법은 앞서 보여준 방법과 동일한데 결과 로그는 두개의 테이블에 넣는다. 

1
2
3
 
Hibernate: insert into TESTSCHEMA.Customer (customerName, customerId) values (?, ?)
Hibernate: insert into TESTSCHEMA.CustomerDetail (creditScore, customerAddress, rewardPoints, customerId) values (?, ?, ?, ?)
cs




posted by 제스트
:
개발관련/Spring 2015. 12. 4. 13:59
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.zest.hibernate.chapter1;
 
import java.util.Calendar;
import java.util.Date;
 
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
 
@Entity
@Table(name = "EmployeeInfo")
public class Employee {
 
    @Id
    @Column(name = "EmployeeId", nullable = false)
    /**
     * sequence table을 생성.
     * name= sequence table의 alias 이름.
     * table은 sequence table의 이름.  
     * pkColumnName 은  sequence table의 column이름.
     * pkColumnValue은  sequence table 값을 저장하는 이름.. 
     * 
     */
    
    @TableGenerator(name = "empid", table = "emppktb", pkColumnName = "empkey"
    , pkColumnValue = "empvalue", allocationSize=1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "empid")
    private int empId;
    private String empName;
 
    // db에 등록은 안되고 객체에서 db와 별도의 기능이 필요할 경우 사용되는 어노테이션.
    @Transient
    private String empPassword;
    @Column(nullable = false)
    private String empEmailAddress;
 
    @Basic
    private boolean isPermanent;
 
    @Temporal(TemporalType.DATE)
    private Calendar empJoinDate;
 
    // @Basic
    @Temporal(TemporalType.TIMESTAMP)
    private Date empLoginTime;
 
    public String getEmpPassword() {
        return empPassword;
    }
 
    public void setEmpPassword(String empPassword) {
        this.empPassword = empPassword;
    }
 
    public String getEmpEmailAddress() {
        return empEmailAddress;
    }
 
    public void setEmpEmailAddress(String empEmailAddress) {
        this.empEmailAddress = empEmailAddress;
    }
 
    //
    public boolean isPermanent() {
        return isPermanent;
    }
 
    public void setPermanent(boolean isPermanent) {
        this.isPermanent = isPermanent;
    }
 
    public Calendar getEmpJoinDate() {
        return empJoinDate;
    }
 
    public void setEmpJoinDate(Calendar empJoinDate) {
        this.empJoinDate = empJoinDate;
    }
 
    public Date getEmpLoginTime() {
        return empLoginTime;
    }
 
    public void setEmpLoginTime(Date empLoginTime) {
        this.empLoginTime = empLoginTime;
    }
 
    public int getEmpId() {
        return empId;
    }
 
    public void setEmpId(int empId) {
        this.empId = empId;
    }
 
    public String getEmpName() {
        return empName;
    }
 
    public void setEmpName(String empName) {
        this.empName = empName;
    }
 
}
 
cs


먼저 employee라는 클래스를 생성하자. 

@Entity 라는 어노테이션이 등장한다. 이넘은 db의 table을 지징하는넘이다. nosql에선 collection정도? 


@Table은 table의 이름을 바꾸고자 할 때 사용한다. 만약 이 어노테이션이 생략 되면 테이블 이름은 클래스 명과 동일하게 된다. 


@TableGenerator는 Sequence Table을 정의할 때 사용한다. 옵션은 다음과 같다. 

 name= sequence table의 alias 이름.

 table은 sequence table의 이름.  

 pkColumnName 은  sequence table의 column이름.

 pkColumnValue은  sequence table 값을 저장하는 이름.. 


@GenerartedValue는 auto increment 의 옵션이다. 이때 위의 예제는 segence table의 값을 사용할 때의 예제 이다. 


@Transient는 database의 table과 상관없이 employee 객체 안에서 다른 객체 또는 무언가 다른 작업을 하고 싶을 때 사용하는 옵션이다. 결국 db에 영향을 주지는 않는다. 


@Basic은 lazy 관련 옵션이다. 


@Temporal은 시간,날짜에 대한 옵션을 줄때 사용하는 어노테이션이다. 


이제 실행해보자..

1
2
3
4
5
6
7
8
9
10
11
 
    @Test
    public void entityTest1(){
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Employee.class);
        config.configure("hibernate.cfg.xml");
        
        new SchemaExport(config).create(true,true);
        
        
    }
cs


아주 간단한 소스이다. 여기서 중요한 것은 create의 옵션이다. 첫번째 두번째 파라미터의 설명은 

script print the DDL to the console, export export the script to the database 

해석하자면 첫번째 것은 니가 실행하고자 하는거 콘솔에 찍을까? 두번째 것은 스크립트 실행할래? 이다. 두번째 것이 false로 되어있음 table이 생성되지 않는다.  그럼 로그를 살펴보자. 

1
2
3
4
5
6
7
8
INFO : org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=user, password=****}
drop table TESTSCHEMA.EmployeeInfo
drop table TESTSCHEMA.emppktb
create table TESTSCHEMA.EmployeeInfo (EmployeeId integer not null, empEmailAddress varchar(255) not null, empJoinDate date, empLoginTime timestamp, empName varchar(255), isPermanent smallint not null, primary key (EmployeeId))
create table TESTSCHEMA.emppktb ( empkey varchar(255),  sequence_next_hi_value integer ) 
INFO : org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete
INFO : org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:derby://localhost:1527/hibernateDb
 
cs


create 함수를 콜을 하면 기존의 테이블을 삭제하고 생성하는것이 보일것이다. 


이제 데이터를 추가해보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @Test
    public void entityTest2(){
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Employee.class);
        config.configure("hibernate.cfg.xml");
        
//        new SchemaExport(config).create(true,true);
        
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
        
        session.beginTransaction();
        
        Employee alex = new Employee();
        alex.setEmpName("Alex Berry");
        alex.setEmpEmailAddress("aaa@aa.com");
        session.save(alex);
        
        session.getTransaction().commit();
    }
cs


세션을 한개 만들어서 트랜잭션을 시작하게 된다. 작업을 마치고 commit으로 종료를 하게 된다. 

굉장히 심플하다. 아마도 jpa에서 이부분이 조금 변경 될 것이다. session 관련은 bean으로 뺄 것이며, 트랜잭션은 어노테이션 기반으로 처리 할것이고 repository 에서 save등등 sql문을 처리 할 것이다. 어쨋든 하이버네이트에선 위와 같이 처리하게 된다. 


위의 junit테스트를 실행해보면 insert 구문이 나올 것이다. 

empId의 경우는 sequence table에서 가져오므로 그냥 추가가 될것이다. 


이번에는 create함수를 사용하고 모든 컬럼에 값을 넣어보자. 


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
    @Test
    public void entityTest3(){
        //hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Employee.class);
        //db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
        
        //db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        //<property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시 마찬가지임.
        new SchemaExport(config).create(true,true);
        
        //아래 두개의 구문은 객체를 트랜잭션을 컨트롤. 
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
        
        session.beginTransaction();
        
        Employee alex = new Employee();
//        alex.setEmpId(2);
        alex.setEmpName("Alex Berry11");
        alex.setEmpEmailAddress("alex@hibernate.com");
        alex.setEmpPassword("alexpass");
        alex.setEmpJoinDate(new GregorianCalendar(2009,05,26));
        alex.setEmpLoginTime(Date.valueOf("2010-06-05"));
        session.save(alex);
        
        session.getTransaction().commit();
        session.close();
    }
cs


기존 데이터가 삭제되고 한개만 추가 될것이다. 


https://github.com/zest133/hibernateTest.git 소스는 다운받을 수 있다. 

posted by 제스트
:
개발관련/Spring 2015. 12. 4. 11:46


(출처:http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/reference/ko/html_single/)

하이버네이트의 기본 개념은 위와 같다.  

orm(object relation mapping )기반 이며, spring data의 jpa 역시 내부적으로 hibernate를 감싸서 만들었다. 


예제들은 아파치에서 무료로 제공하는 derby 를 사용한다. 사실 머 db는 상관없다. 



먼저 pom파일을 보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.4.0.GA</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.3.2.GA</version>
        </dependency>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derbyclient</artifactId>
            <version>10.12.1.1</version>
        </dependency>
cs


hibernate를 추가하고 derby database client를 추가한다. 


context.xml을 살펴보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
 
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="configLocation" >
      <value>hibernate.cfg.xml</value>
  </property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
      <ref bean="sessionFactory" />
    </property>
</bean>
 
</beans>
 
cs


hibernate.cfg.xml이라는 설정파일이 보이고 hibernateTemplate이라는 객체가 보인다. 위와 같이 설정해주자. 


다음은 hibernate.cfg.xml 설정이다. 

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
 
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
  
     <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
       <property name="connection.url">jdbc:derby://localhost:1527/hibernateDb</property
     <property name="connection.username">user</property>
     <property name="connection.password">password</property>
     <!-- SQL dialect -->
     <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
 
     <property name="hibernate.default_schema">TESTSCHEMA</property>
     <!--  session을 사용하기 위한 정의 없으면 No CurrentSessionContext configured! 요에러 뜬다.  -->
     <property name="current_session_context_class">thread</property>
     <!-- JDBC connection pool (use the built-in) -->
     <property name="connection.pool_size">2</property>
 
 
     <!-- Echo all executed SQL to stdout -->
     <property name="show_sql">true</property>
 
     <!-- Drop and re-create the database schema on startup 
     <property name="hbm2ddl.auto">create</property>-->
  </session-factory>
</hibernate-configuration>
cs


여기서 중요한 건 dialect이다. 모든 db마다 dialect가 있고 아마도 저넘이 database마다 존재 하는 것으로 봐선 sql문으로 변환을 해주는 느낌이다. 그리고 마지막 부분의 hdm2ddl.auto 라는 넘이 있는데 저 구분을 활성화 하면 할때마다 기존 것들을 지우고 다시 만든다.  derby는 설치하기 쉬우니 생략~


모든 설정이 끝났다. 다음 글에서 부터 예제를 만들어보자. 



posted by 제스트
:
개발관련/Spring 2015. 11. 30. 15:13

pom.xml은 바뀐게 없다. 저번에 설명을 못한 부분이 있는데 weaving이라는 것이다. 이부분은 

http://najuung.tistory.com/65 이분의 사이트를 참조하라 


바로 소스로 들어가자. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
 
    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="com.gno.sample"></context:component-scan>
    
    <aop:aspectj-autoproxy />
    
 
    <bean id="simpleCalcService" class="com.gno.sample.service.SimpleCalcServiceImpl"></bean>
    <bean id="calcDao" class="com.gno.sample.dao.CalcDaoImpl"></bean>
 
    <bean id="loggingAspect" class="com.gno.sample.aop.SimpleAopAspect"></bean>
    
</beans>
 
cs


기존 aop:config에서 scan과 annotation-config, autoproxy 가 추가 되었다. 그리고 기존 pointcut과 expression등은 사라졌다.  simpleAppAspect 클래스를 살펴보자. 


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
 
package com.gno.sample.aop;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
 
@Aspect
public class SimpleAopAspect {
 
    @Before("execution(* com.gno.sample.dao.CalcDAO.*(..)) ")
    public void before(JoinPoint joinPoint) {
        System.out.println("before!");
        Signature signature = joinPoint.getSignature();
        Object target = joinPoint.getTarget();
        Object[] args = joinPoint.getArgs();
 
        System.out.println("Signature : " + signature.toString());
        System.out.println("target : " + target.toString());
        System.out.println("name : " + signature.getName());
        System.out.println("longName : " + signature.toLongString());
        System.out.println("shortName : " + signature.toShortString());
    }
 
    @After("execution(* com.gno.sample.dao.CalcDAO.*(..))")
    public void after(JoinPoint joinPoint) {
        System.out.println("after!");
        Signature signature = joinPoint.getSignature();
        Object target = joinPoint.getTarget();
        Object[] args = joinPoint.getArgs();
 
        System.out.println("Signature : " + signature.toString());
        System.out.println("target : " + target.toString());
        System.out.println("name : " + signature.getName());
        System.out.println("longName : " + signature.toLongString());
        System.out.println("shortName : " + signature.toShortString());
    }
}
cs

@Aspect 라는 annotation으로 선언을 하면 기존 config와 같은 역활을 한다. 이후 @Before 등로 pointcut등을 지정한다. 나머진 같다. 

소스는 https://github.com/zest133/SpringAOPSample/ 

후 왠지 빈약하네 =_=;; 사실 머 별거 없지


posted by 제스트
:
개발관련/Spring 2015. 11. 30. 14:43

Aspect oriented Programming 관점 지향 프로그래밍... 이다. 


(출처:http://ezquest.tistory.com/entry/Spring)


위 그림처럼 logging이라던가 security(login 관련) 또는 transaction 이라던가를 횡단으로 특정한 곳을 보는 관점 지향 하는 프로그래밍이다. 여기에 사족을 좀 덧 붙이자면, 관점 지향이라고 해서 무언가 autowired된 객체를 변환한다던가 또는 기존 객체를 변환한다던가는 하지 못한다. 단지. 내가 보고자 하는 부분에 대해 지정한 일을 한다는 것이다. 


예를 들면, 이런 이런 객체에 로깅을 한다. 또는 exception에 대해 로그를 남긴다. 또는 전체 세션에 대해 로그인을 감지한다. 마지막으로 트랜잭션에 대해 처리를 한다. 이런 일들을 도맡아 한다. 멤캐쉬 redis캐쉬, ehcached 역시 aop로 처리를 한다. 


그럼 바로 aop 관련 예제를 보자. 

1
2
3
4
5
6
7
8
9
10
11
<!-- Aspectj -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
        </dependency>
cs

pom.xml 설정은 위에 두가지를 선언한다. 


다음은 context.xml 설정이다. 

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
 
    
    
 
    <bean id="simpleCalcService" class="com.gno.sample.service.SimpleCalcServiceImpl"></bean>
    <bean id="calcDao" class="com.gno.sample.dao.CalcDaoImpl"></bean>
 
    <bean id="loggingAspect" class="com.gno.sample.aop.SimpleAopAspectXML"></bean>
    
    
    <!--
        aspect: 관점. 걍 aspect에 이용할 클래스로 라고 지정
        advice: 어느 시점에 실행 될지 정하는 구분자 (before, after, throw, around)
        pointcut: 쳐다보고 있는 기준 함수 정의 
        expression: pointcut 에 입력하는 문법 (<리턴타입> <클래스>.<메소드><(매개변수)>)
     
     -->
    
    
    <aop:config>
        <aop:aspect id="aspect" ref="loggingAspect">
            <aop:pointcut expression="execution(* com.gno.sample.dao.CalcDAO.*(..))" id="pointCut"/>
            
            <aop:before method="before" pointcut-ref="pointCut"/>
            <aop:after method="after" pointcut-ref="pointCut"/>
        </aop:aspect>
    </aop:config>
    
    
</beans>
 
cs

마지막 부분에 aop:config 라는 설정이 있다. 

pointcut은 어느 객체를 횡단간 관심을 주냐는 거다. 이후 특정 메소드에 before,after, after-returning, after-throwing등 설정을 하여 pointcut의 id를 넘겨준다. 


그리고 미리 설정해놓은 loggingAspect를 aop:config에 전달한다. 

그럼 loggingAspect 소스를 보자. 


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
package com.gno.sample.aop;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
 
public class SimpleAopAspectXML {
 
    public void before(JoinPoint joinPoint) {
        System.out.println("before!");
         Signature signature = joinPoint.getSignature();
          Object target = joinPoint.getTarget();
          Object[] args = joinPoint.getArgs();
          
          System.out.println("Signature : " + signature.toString());
          System.out.println("target : " + target.toString());
          System.out.println("name : " + signature.getName());
          System.out.println("longName : " + signature.toLongString());
          System.out.println("shortName : " + signature.toShortString());
    }
 
    public void after(JoinPoint joinPoint) {
        System.out.println("after!");
         Signature signature = joinPoint.getSignature();
          Object target = joinPoint.getTarget();
          Object[] args = joinPoint.getArgs();
          
          System.out.println("Signature : " + signature.toString());
          System.out.println("target : " + target.toString());
          System.out.println("name : " + signature.getName());
          System.out.println("longName : " + signature.toLongString());
          System.out.println("shortName : " + signature.toShortString());
    }
}
cs

그럼 실행 코드를 보고 설명한다. 
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
package com.gno.sample.aop;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
 
import com.gno.sample.service.SimpleCalcService;
 
//@ContextConfiguration(locations={"file:src/main/resources/aop-context.xml"})
@ContextConfiguration(locations={"file:src/main/resources/aop-context_xml.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class AopTest {
    
    @Autowired
    public SimpleCalcService simpleCalcService;
    
    @Test
    public void test(){
        
        int returnVal = simpleCalcService.add(11);
        
        
        assertThat(returnVal, is(2));
        
    }
}
 
cs

simpleCalcService.add가 실행되면 bean에 설정해놓은 pointcut과 일치하므로 simpleAspectXML객체의 before와 after가 실행될 것이다. add함수가 실행되기전, add함수가 실행되고 난후 실행된다. 

aop 설명은 여기까지 다음은 annotation 기반 을 다음에 살펴보자. 

소스 출처는 https://github.com/gnogun/SpringAOPSample.git << 요기로 그노야 고마워. 


posted by 제스트
: