Aop 簡單的例子與使用


Aop 的作用

Aop: 面向切面編程
aop 的主要作用是運行一個函數的前后,運行另外的函數。

例子: 我們以一個日志為例,我們運行一個函數,需要記錄這個函數的運行時間 和他的運行結果
最簡單的函數

public class SimpleExample implements SExample {
    @Override
    public String orinFun(String arg){
        return  arg;
    }
}

最簡單的寫法

我們直接在該函數記錄時間和結果

public String orinFun(String arg){
        System.out.println("運行時間"+new Date().toString());
        System.out.println("結果"+arg);
        return  arg;
    }

當我們需要打印多個函數的運行時間這樣的寫法就非常冗余,且不易擴展,我們可以通過代理來解決。

代理

接口

public interface SExample {
    String orinFun(String arg);
}

代理

public class SimpleProxy implements InvocationHandler {

    private Object obj;

    public SimpleProxy(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();//你也可以根據代理名字的不同,做不同的代理方式 if(methodName.equals("*"))
        System.out.println("運行時間"+new Date().toString());
        Object res = method.invoke(obj, args);
        System.out.println("結果"+res);
        return res;
    }
}

測試

 @Test
    void tesProxy(){
        SimpleExample simpleExample = new SimpleExample();
        SExample simpleExampleProxy = (SExample) Proxy.newProxyInstance(SimpleProxy.class.getClassLoader(),
                new Class<?>[]{SExample.class},new SimpleProxy(simpleExample));
        simpleExampleProxy.orinFun("test");
    }

這樣寫就很方便了,一個類只需要寫一個代理就行
spring boot 提供更加方便的寫法就是aop

AOP的使用

1.引入包

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.在啟動類上添加@EnableAspectJAutoProxy(exposeProxy = true)

即只有exposeProxy為true時,才會把proxy動態代理對象設置到AopContext上下文中。

@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class DemoApplication {

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

}

3.定義切片類

A.在類前面加上 @Aspect @Component注解
B. 定義切面 @Pointcut("execution(* com.example.demo.HelloWorld.*(..))"),既在那些函數外增添操作
C.定義具體的執行操作
D.什么時候執行操作 @Before @after AfterThrowing...

@Aspect
@Component
public class AopHandler {

    @Pointcut("execution(* com.example.demo.HelloWorld.*(..))")
    public void test(){

    }
    @Before("test()")
    public void before() throws Throwable {
        System.out.println("代理----前----CurrentTime = " + System.currentTimeMillis());
    }

    @After("test()")
    public void afterReturning() throws Throwable {
        System.out.println("代理----后----CurrentTime = " + System.currentTimeMillis());
    }
}

Aop Around

我們可以將 before 和 after 和 afterthrowing 都放在Around 來做,更加的方便

@Aspect
@Component
public class AopDetailHandler {
    @Pointcut("execution(* com.example.demo.DetailTest.print(..))")
    public void pointCut(){
    }

    @Pointcut("execution(* com.example.demo.DetailTest.doPrint(String))")
    public void pointCut2(){
    }

    @Before("pointCut()")
    public void before(JoinPoint joinPoint) throws Throwable {
        System.out.println("得到切片的參數"+Arrays.toString(joinPoint.getArgs()));
        System.out.println("得到運行的類"+joinPoint.getSignature());
        System.out.println("代理----前----CurrentTime = " + System.currentTimeMillis());
    }

    @Around("pointCut2()")
    public Object run1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        // before
        // 獲取方法名
        String methodName = proceedingJoinPoint.getSignature().toString();
        System.out.println("方法名"+methodName);
        Object[] args = proceedingJoinPoint.getArgs();
        System.out.println("參數"+ Arrays.toString(args));
        // 獲取掉切片目標類
        String entity = proceedingJoinPoint.getTarget().getClass().getName();
        System.out.println("獲取調切片"+entity);
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();//test方法的返回值
            // after
            System.out.println(result.toString());
        } catch (Exception ex) {
            // after throwing
            System.out.println(ex.toString());
        }
        return result;
    }
}

gitee

https://gitee.com/jefferyeven/Aop_simple_use


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM