# Spring Framework part - 2

### AOP
AOP is one of the core concepts for Spring, AOP stands for aspect-oriented programming. It's an idea that directs you on how to code, just like OOP. </br>
We can enhance our program without changing the original code with AOP concept.</br>
To use AOP in Spring, we  need to add the dependency

```
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.4</version>
    </dependency>
``` 
Then we can create a sample class, exampleDao

```
@Repository
public class exampleDao {

    public void FirstTest() {
        System.out.println(System.currentTimeMillis());
        System.out.println("exampleDao do first test...");
    }

    public void SecondTest() {
        System.out.println("exampleDao do second test...");
    }

    public void ThirdTest() {
        System.out.println("exampleDao do third test...");
    }
}
``` 
Then we run a test in our test class

```
public class test {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        exampleDao exampleDao = context.getBean(exampleDao.class);
        exampleDao.FirstTest();
    }
}
``` 
Our result is 

```
1654017793015
exampleDao do first test...

``` 
Let's try again with the second method

```
public class test {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        exampleDao exampleDao = context.getBean(exampleDao.class);
        exampleDao.SecondTest();
    }
}

``` 
Our result is 

```
1654017834214
exampleDao do second test...

``` 
How could that happen? We put the "        System.out.println(System.currentTimeMillis());" statement in the FirstTest( ) method only, how could the SecondTest( ) method have that?</br>
Here, we used AOP in Spring. To implement this process, we need to do some modifications to our code. First, we need to enable the AOP function in our SpringConfig class.

```
@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class SpringConfig {
}
``` 
Next, we need to tell Spring which method we want to share with other methods.

```
@Component
@Aspect
public class AOPService {
    @Pointcut("execution(void com.example.dao.exampleDao.SecondTest())")
    private void pt(){}

    @Before("pt()")
    public void before(){
        System.out.println(System.currentTimeMillis());
    }
}
``` 
Now, both FirstTest( ) and SecondTest ( ) method have acces to "System.out.println(System.currentTimeMillis());" statement.

If we need to retrieve data in the AOP process, we can use JoinPoint class

```
    @Before("pt()")
    public void before(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        System.out.println(System.currentTimeMillis());
    }
``` 
If we want called the method at different place, we can use Around annotation:

```
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object proceed = proceedingJoinPoint.proceed();
        return proceed;
    }
``` 
### Transaction

to be continued
