<์ถœ์ฒ˜ ์ธํ”„๋Ÿฐ>

 

์ฝ”๋กœ๋‚˜ ํœด์œ ์ฆ์œผ๋กœ ๊ธฐ๋ ฅ์—†์Œ๊ณผ ์กฐ๊ธˆ๋งŒ ์›€์ง์—ฌ๋„ ์˜จ๋ชธ์ด ์•„ํ””์„ ๊ฒช๊ณ  ์žˆ์ง€๋งŒ, ์•‰์•„์„œ ๊ณต๋ถ€ํ•˜๋Š” ๊ฑด ํฐ ๊ธฐ๋ ฅ์ด ๋“ค์ง€ ์•Š์•„ ์–ด์ฐŒ์ €์ฐŒ ํ•˜๊ณ  ์žˆ๋‹ค. ์˜ค๋Š˜์€ ๋…ธํŠธ๋ถ ์กด์ด ์žˆ๋Š” ์Šคํ„ฐ๋””์นดํŽ˜์—์„œ ๊ณต๋ถ€๋ฅผ ํ–ˆ๋Š”๋ฐ ์•„์ฃผ ์พŒ์ ํ•˜๊ณ  ์ข‹๋‹ค. ์–ด๋Š ํ•œ์ผ ์—” ๋ฒŒ๋ ˆ๊ฐ€ ์žˆ๋Š”์ง€ ์‚๋ฆฌ๋ฆญ- ํ•˜๊ณ  ์šธ์–ด ์ž์—ฐ์นœํ™”์ ์ธ ๋Š๋‚Œ์ด ๋ฌผ์”ฌ๋‚œ๋‹ค. ํ”ผ๊ณค์— ์ฉ”์–ด ๋‹คํฌ์„œํด์ด ์ฝ”๊นŒ์ง€ ๋‚ด๋ ค์™”์ง€๋งŒ ์˜ค๋Š˜๋„ ํ™”์ดํŒ…!!

 



๐Ÿงธ 

 


 

๐Ÿงธ ๊ตฌ์กฐํŒŒ์•… ๋ ˆ์ธ ๊ผฌ์šฐ- ๐Ÿงธ

 • lifecycle

ใ„ด class : NetworkClient, beanLifeCycleTest

 


 

โœ”๏ธ  ๊ฒฐ๊ณผ๊ฐ’ null

 

โ–บ  BeanLifeCycleTest

@Configuration
static class LifeCycleConfig {
         @Bean
         public NetworkClient networkClient() {
             NetworkClient networkClient = new NetworkClient();
             networkClient.setUrl("http://hello-spring.dev");
             return networkClient;
         }
}

 

@Configuration

:  bean์œผ๋กœ ๋“ฑ๋กํ•˜๊ธฐ์œ„ํ•ด ์„ค์ • ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•˜๋ฉฐ bean์ด ๋“ฑ๋ก๋  ๋•Œ ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅํ•ด์ค€๋‹ค.

 

 

@Bean

:  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์†Œํ”„ํŠธ์›จ์–ด ์ปดํฌ๋„ŒํŠธ(์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋…๋ฆฝ๋œ ์กฐ๊ฐ)์ด๋‹ค. 

 

 

๋นˆ์€ NetworkClient ํƒ€์ž…์˜ networkClient๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. NetworkClient๋Š” ๊ฐ์ฒด ์ƒ์„ฑ ํ›„ ๋ฐ”๋กœ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š๊ณ  ์œ ์—ฐํ•˜๊ณ  ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ์ฒด๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•œ ํ›„ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋ณ€์ˆ˜ networkClient๋ฅผ ์„ ์–ธํ•œ๋‹ค. NetworkClient๋Š” ๋‹ค๋ฅธ ํด๋ž˜์Šค๋กœ ์กด์žฌํ•˜๋ฉฐ ๊ทธ ํด๋ž˜์Šค ๋‚ด์—๋Š” setter๋ฅผ ํ†ตํ•ด url์„ ๋ฐ›๊ณ ์ž ํ•  ๊ฒƒ์ด๋‹ค. (๋‹ค๋ฅธ ํด๋ž˜์Šค์— url์„ ๋„˜๊ธฐ๊ธฐ ์œ„ํ•ด์„œ ๋นˆ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ!) ํ•ด๋‹น url์„ ์„ค์ •ํ•ด์ค€ํ›„ networkClient๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋œ๋‹ค.

 

 

Q. ๋งŒ์•ฝ NetworkClient ํƒ€์ž…์œผ๋กœ ๋นˆ์„ ์„ค์ •ํ•ด๋‘๊ณ  ํด๋ž˜์Šค ์ด๋ฆ„์ด NetWorkClient๋กœ ๋‹ค๋ฅด๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋Š”๊ฐ€?

A. ๋‹น์—ฐํ•˜๊ฒŒ๋„ ์ œ๋Œ€๋กœ ์ˆ˜ํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค. ๋นˆ์˜ ํƒ€์ž…์ด ๋‹ค๋ฅด๊ฒŒ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ค์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— ์˜๋„๋Œ€๋กœ ๋™์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค.

 

 

 

- @Configuration ์ถœ์ฒ˜

 

[Spring] @Configuration ์ด๋ž€?

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” @Configuration์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์ ์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด๋ณผ๊นŒ ํ•œ๋‹ค. 1. @Configuration ์ด๋ž€? " data-ke-type="html"> HTML ์‚ฝ์ž… ๋ฏธ๋ฆฌ๋ณด๊ธฐํ•  ์ˆ˜ ์—†๋Š” ์†Œ์Šค Spring์—์„œ Bean์„ ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, ์„ค

blogshine.tistory.com

 

- @bean ์ถœ์ฒ˜

 

๐ŸŸข [Spring] ์Šคํ”„๋ง ๋นˆ(Bean) ์ด๋ž€?

๐Ÿ“Œ ์Šคํ”„๋ง ๋นˆ(Bean) ์ด๋ž€? ๋นˆ(Bean)์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์†Œํ”„ํŠธ์›จ์–ด ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. ์ฆ‰, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ๋œปํ•˜๋ฉฐ, ํ•˜๋‚˜ ์ด์ƒ์˜ ๋นˆ(Bean)์„ ๊ด€๋ฆฌ

dev-wnstjd.tistory.com

 

 

 

 

โ–บ  NetworkClient

public NetworkClient() {
	System.out.println("์ƒ์„ฑ์ž ํ˜ธ์ถœ, url = " + url); 
	connect();
	call("์ดˆ๊ธฐํ™” ์—ฐ๊ฒฐ ๋ฉ”์‹œ์ง€");
}

 

๊ฐ€์žฅ ์ฒซ๋ฒˆ์งธ ์ฝ”๋“œ๋กœ ์ƒ์„ฑ์ž ๋ถ€๋ถ„์—์„œ connect( );๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์•„์ง url์„ setter๋กœ ๋ฐ›์•„์˜ค๊ธฐ์ „ connect( );๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํ•˜๊ฒŒ๋„ null ๊ฐ’์ด ๋‚˜์˜ฌ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.

 

 

 

 

 


 

 

 

Q. ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ์„ ํ•˜๋Š” ์ด์œ ๋Š”?

A. ์Šคํ”„๋ง ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ์ œ๋Œ€๋กœ ์ง€์ผœ ์˜ค๋ฅ˜ ๋ฐœ์ƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.

 

 

 

โœ”๏ธ  ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ

 

โ–บ  ์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฒคํŠธ ๋ผ์ดํ”„ ์‚ฌ์ดํด

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ - ์Šคํ”„๋ง ๋นˆ ์ƒ์„ฑ - ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… - ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ - ์‚ฌ์šฉ - ์†Œ๋ฉธ์ „ ์ฝœ๋ฐฑ

: ์Šคํ”„๋ง ๋นˆ์ด ์ƒ์„ฑ๋œ ํ›„ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ์ด๋ค„์ ธ์•ผํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ฃผ์ž…์ด ๋ชจ๋‘ ์ด๋ค„์ง€๊ณ  url์„ ๋ฐ›์•„์˜ค์ง€์•Š๊ณ , ๋นˆ์ด ์ฃผ์ž…์ด ๋˜๊ธฐ ์ „ connect( )ํ•˜๊ณ ์ž ํ–ˆ๋‹ค. ๊ฒฐ๊ณผ๊ฐ’์€ null๋กœ ๋‚˜์˜ค๋ฉฐ ์˜๋„๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋ถ€๋ถ„์„ ์ค„์ด๊ธฐ ์œ„ํ•ด ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.  ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ์„ ์ฝ”๋“œ์— ๋„ฃ์–ด ์˜์กด๊ด€๊ณ„๊ฐ€ ๋ชจ๋‘ ์ฃผ์ž…๋˜๊ณ ๋‚˜์„œ ๊ทธ ํ›„์— ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

 

 

 

โ–บ  ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ์˜ ์žฅ์ 

1. ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ๋”ฐ๋ผ ๋งค๋ฒˆ ๋นˆ์ด ์ผ๊ด€๋œ ์ƒํƒœ์—์„œ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.  

2. ๋นˆ์ด ํŒŒ๊ดด๋˜๊ธฐ ์ „ ๋ฆฌ์†Œ์Šค๋ฅผ ์ •๋ฆฌํ•  ์‹œ๊ฐ„์„ ์ค€๋‹ค.

3. ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ํ•œ ๊ณณ์— ๋ชจ์•„๋‘ฌ์„œ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์ข‹๋‹ค.

 

 

 

 


 

 

 

โœ”๏ธ ์ธํ„ฐํŽ˜์ด์Šค InitializingBean, DisposableBean

 

โ–บ  NetworkClient

    @Override
    public void afterPropertiesSet() throws Exception {
    	connect();
	call("์ดˆ๊ธฐํ™” ์—ฐ๊ฒฐ ๋ฉ”์‹œ์ง€");
    }

 

afterPropertiesSet( )

:  ์ธํ„ฐํŽ˜์ด์Šค InitializingBean์„ ์ƒ์†๋ฐ›์œผ๋ฉด ๊ทธ ์•ˆ์— ์ •์˜๋œ afterPropertiesSet ๋ฉ”์„œ๋“œ๋กœ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ๋๋‚˜๋ฉด ์ดˆ๊ธฐํ™”๋ฅผ ์ง€์›ํ•œ๋‹ค.

 
 
    @Override
    public void destroy() throws Exception {
        disConnect();
    }

 

destroy( )

:  ์ธํ„ฐํŽ˜์ด์Šค DisposableBean์„ ์ƒ์†๋ฐ›์œผ๋ฉด ๊ทธ ์•ˆ์— ์ •์˜๋œ destroy ๋ฉ”์„œ๋“œ๋กœ ๋นˆ์ด ํŒŒ๊ดด๋  ๋•Œ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

 

 

๊ฒฐ๋ก  : ์ƒ์†๋œ ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋˜์–ด์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ ธ์™€ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค. ๋˜ํ•œ ์Šคํ”„๋ง์— ํŠนํ™”๋˜์–ด์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ผ์„œ ์Šคํ”„๋ง์ด ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์™ธ๋ถ€๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

 

 

 

- InitializingBean ์ถœ์ฒ˜

 

InitializingBean (Spring Framework 6.1.12 API)

Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: e.g. to perform custom initialization, or merely to check that all mandatory properties have been set. An alternative to implementing Initiali

docs.spring.io

 

 

- DisposableBean ์ถœ์ฒ˜

 

DisposableBean (Spring Framework 6.1.12 API)

Interface to be implemented by beans that want to release resources on destruction. A BeanFactory will invoke the destroy method on individual destruction of a scoped bean. An ApplicationContext is supposed to dispose all of its singletons on shutdown, dri

docs.spring.io

 

 

 

 

 


 

 

 

 

โœ”๏ธ  ๋นˆ ๋“ฑ๋ก์— ์ดˆ๊ธฐํ™”, ์†Œ๋ฉธ ๋ฉ”์„œ๋“œ ์ง€์ •

 

โ–บ  BeanLifeCycleTest

์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

@Bean(initMethod = "init", destroyMethod = "close")
public NetworkClient networkClient() {
    NetworkClient networkClient = new NetworkClient();
    networkClient.setUrl("http://hello-spring.dev");
    return networkClient;
}

 

initMethod

: ์ดˆ๊ธฐํ™” ์ค‘์— ๋นˆ ์ธ์Šคํ„ฐ์Šค์—์„œ ํ˜ธ์ถœํ•  ๋ฉ”์„œ๋“œ์˜ ์„ ํƒ์  ์ด๋ฆ„์ด๋‹ค. 

 

 

destroyMethod

: ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๋‹ซ์„ ๋•Œ ๋นˆ ์ธ์Šคํ„ด์Šค์—์„œ ํ˜ธ์ถœํ•œ ๋ฉ”์„œ๋“œ์˜ ์„ ํƒ์  ์ด๋ฆ„์ด๋‹ค. ๋นˆ ๋ฉ”์„œ๋“œ์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•ด destroy๊ฐ€ ์žˆ๋Š”์ง€ ์œ ์ถ”ํ•˜๋ฉฐ close( ), shutdown( ) ์ด๋ผ๋Š” ์ด๋ฆ„์˜ ์ธ์ˆ˜ ์—†๋Š” ๊ณต๊ฐœ ๋ฉ”์„œ๋“œ๋งŒ ๊ฐ์ง€ํ•˜์—ฌ ์ž๋™์ ์œผ๋กœ ์‹คํ–‰ํ•œ๋‹ค.

 

 

 

- initMethod์™€ destroyMethod ์ถœ์ฒ˜

 

Bean (Spring Framework 6.1.12 API)

The optional name of a method to call on the bean instance upon closing the application context, for example a close() method on a JDBC DataSource implementation, or a Hibernate SessionFactory object. The method must have no arguments but may throw any exc

docs.spring.io

 

 

 

โ–บ  NetworkClient

public void init() { 
	System.out.println("NetworkClient.init"); 
	connect();
	call("์ดˆ๊ธฐํ™” ์—ฐ๊ฒฐ ๋ฉ”์‹œ์ง€");
}

public void close() {
         System.out.println("NetworkClient.close");
         disConnect();
}

 

init( )

:  initMethod๋ฅผ ํ˜ธ์ถœํ•  ์„ ํƒ์  ์ด๋ฆ„์ด ๋˜๊ฒ ๋‹ค.

 

 

close( )

: destroyMethod๋ฅผ ํ˜ธ์ถœํ•  ์„ ํƒ์  ์ด๋ฆ„์ด ๋˜๊ฒ ๋‹ค.

 

 

์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ์Šคํ”„๋ง ์ฝ”๋“œ์— ์˜์กดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์„ค์ • ์ •๋ณด์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•˜์ง€๋งŒ ์Šคํ”„๋ง์—์„œ ๊ถŒ๊ณ ํ•˜๋Š” ๋ฐฉ์‹์€ ์•„๋‹ˆ๋‹ค. ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ๋„ ์žˆ์ง€๋งŒ ์ด๋ฆ„์„ ๋ช…์‹œํ•˜๋Š” ๊ฒƒ์—์„œ ์ด๋ฆ„์ด ๋‹ฌ๋ผ์งˆ ๊ฒฝ์šฐ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ด ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ๋„)

 

 

 

 

 


 

 

 

 

 

โœ”๏ธ  ์• ๋…ธํ…Œ์ด์…˜ @PostConstruct, @PreDestroy

 

โ–บ  NetworkClient

์Šคํ”„๋ง์—์„œ ๊ฐ€์žฅ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

	@PostConstruct
	public void init() {
		System.out.println("NetworkClient.init"); connect();
		call("์ดˆ๊ธฐํ™” ์—ฐ๊ฒฐ ๋ฉ”์‹œ์ง€");
	}
    
	@PreDestroy
	public void close() {
		System.out.println("NetworkClient.close");
		disConnect();
	}

 

 

@PostConstruct

:  ์˜์กด์„ฑ ์ฃผ์ž…์ด ์™„๋ฃŒ๋œ ํ›„ ์‹คํ–‰๋˜๋Š” ๋ฉ”์„œ๋“œ์— ์‚ฌ์šฉํ•˜๋ฉฐ ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ๋Š” ํ•˜๋‚˜๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค. 

 

 

@PreDestroy

:  ์ธ์Šคํ„ด์Šค๊ฐ€ ์ œ๊ฑฐ๋˜๊ณ  ์žˆ์Œ์„ ์•Œ๋ฆฌ๋Š” ์ฝœ๋ฐฑ ์•Œ๋ฆผ์ด๋ฉฐ ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ๋ฉ”์„œ๋“œ๋Š” ๋ณด์œ ํ•˜๊ณ  ์žˆ๋˜ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

 

 

 

 

 

- @PostConstruct ์ถœ์ฒ˜

 

PostConstruct (Java(TM) EE 7 Specification APIs)

JavaScript is disabled on your browser. @Documented @Retention(value=RUNTIME) @Target(value=METHOD) public @interface PostConstruct The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any

docs.oracle.com

 

 

 

 

- @PreDestroy ์ถœ์ฒ˜

 

PreDestroy (Java(TM) EE 7 Specification APIs)

JavaScript is disabled on your browser. @Documented @Retention(value=RUNTIME) @Target(value=METHOD) public @interface PreDestroy The PreDestroy annotation is used on methods as a callback notification to signal that the instance is in the process of being

docs.oracle.com

 

 

+ Recent posts