9月16日spring笔记

标签

java

后端

spring

AOP

面向切面编程

jdbc

发布时间:

本文字数:1,024 字 阅读完需:约 5 分钟

AOP 通知的配置

示例

Man.java

package com.aop;

public class Man {
    private String name = "大壮";
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void qq(String toName){
        if(b) {
            throw new RuntimeException("聊天犯规了");
        }
        System.out.println(this.name + "在和[" + toName + "]聊QQ");
    }

    public String mm(){
        System.out.println(this.name + "在聊MM");
        return "很高兴";
    }
}

FBI.java

package com.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;

import java.util.Arrays;

public class FBI {
    public void before(JoinPoint joinPoint){
        Object obj =  joinPoint.getTarget();
        System.out.println("目标对象: "+ obj.getClass().getName());
        Object[] args = joinPoint.getArgs();
        System.out.println("目标对象方法参数: "+ Arrays.toString(args));
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象的方法: "+signature.getName());
    }
    public void after(JoinPoint joinPoint, Object val){
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象方法"+signature.getName()+"执行完毕,返回值"+ val);
    }
    public void throwsException(JoinPoint joinPoint, Throwable e){
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象方法"+signature.getName()+"异常! !, 信息: "+e.getMessage());
    }
    public void afterFinally(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象的方法" + signature.getName() + "执行完毕");
    }
    // 无论有没有异常,都会执行

}

spring-aop.xml

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="man" class="com.aop.Man"></bean>
    <bean id="fbi" class="com.aop.FBI"></bean>
    <aop:config>
<!-- 切面规则   执行在Man的任意方法,参数为任意-->
        <aop:pointcut id="pointcut" expression="execution(* com.aop.Man.*(..))"/>
        <aop:aspect ref="fbi">
<!--            fbi这个bean的before方法 :before为前置通知-->
            <aop:before method="before" pointcut-ref="pointcut"></aop:before>
            <aop:after-returning method="after" pointcut-ref="pointcut" returning="val"></aop:after-returning>
            <!-- 注意:此处的val必须与fbi里面的Object val 参数形参名相同 -->
            <aop:after-throwing method="throwsException" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
            <!-- afterFinally 不管有无异常,都会执行 -->
            <aop:after method="afterFinally" pointcut-ref="pointcut"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

TestAop.java

package com.aop;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    private ClassPathXmlApplicationContext ac;

    @Before
    public void init(){
        ac = new ClassPathXmlApplicationContext("spring-aop.xml");
    }
    @Test
    public void test(){
        Man man = ac.getBean(Man.class);
        man.qq("小美");
        man.mm();
    }
    @After
    public void destroy(){
        ac.close();
    }
}

输出结果

目标对象: com.aop.Man
目标对象方法参数: [小美]
目标对象的方法: qq
目标对象方法qq异常! !, 信息: 聊天犯规了
目标对象的方法qq执行完毕
java.lang.RuntimeException: 聊天犯规了
<!-- ...以下省略若干异常信息 -->
<!-- 如果没有异常,继续输出以下代码 -->
大壮在和[小美]聊QQ
目标对象方法qq执行完毕
目标对象: com.aop.Man
目标对象方法参数: []
目标对象的方法: mm
大壮在聊MM
目标对象方法mm执行完毕,返回值:很高兴

环绕通知

aop 配置: spring-aop.xml

<aop:around method="around" pointcut-ref="pointcut"></aop:around>

FBI.java

public Object around(ProceedingJoinPoint joinPoint){
        Object result = null;
        //前置通知
        Object obj =  joinPoint.getTarget();
        System.out.println("目标对象: "+ obj.getClass().getName());
        try {
            //执行目标对象方法
            result = joinPoint.proceed();
            //返回后通知
            System.out.println("result" + result);
        }catch (Throwable e){
            //执行异常通知
            System.out.println("catch" + e.getMessage());
        }finally {
            //执行最终通知
            System.out.println("finally");
        }
        return result;
    }

结果:

目标对象: com.aop.Man
catch聊天犯规了
finally
目标对象: com.aop.Man
大壮在聊MM
result很高兴
finally

Process finished with exit code 0

alt

采用注解方式配置通知

spring-auto.xml

<?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/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--    通过在的Spring的配置中引入下列元素来启用Spring对@AspectJ的支持-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <context:component-scan base-package="com.auto"></context:component-scan>
</beans>

FBI.java

package com.auto;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import java.util.Arrays;
@Aspect
public class FBI {
    @Before("execution(* com.auto.Man.*(..))")
    public void before(JoinPoint joinPoint){
        Object obj =  joinPoint.getTarget();
        System.out.println("目标对象: "+ obj.getClass().getName());
        Object[] args = joinPoint.getArgs();
        System.out.println("目标对象方法参数: "+ Arrays.toString(args));
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象的方法: "+signature.getName());
    }
    public void afterReturning(JoinPoint joinPoint, Object val){
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象方法"+signature.getName()+"执行完毕, 返回值:"+val);
    }
    public void throwsException(JoinPoint joinPoint, Throwable e){
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象方法"+signature.getName()+"异常! !, 信息: "+e.getMessage());
    }
    public void afterFinally(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("目标对象的方法" + signature.getName() + "执行完毕");
    }

    //环绕通知
    public Object around(ProceedingJoinPoint joinPoint){
        Object result = null;
        //前置通知
        Object obj =  joinPoint.getTarget();
        System.out.println("目标对象: "+ obj.getClass().getName());
        try {
            //执行目标对象方法
            result = joinPoint.proceed();
            //返回后通知
            System.out.println("result" + result);
        }catch (Throwable e){
            //执行异常通知
            System.out.println("catch" + e.getMessage());
        }finally {
            //执行最终通知
            System.out.println("finally");
        }
        return result;
    }
}

Man.java

package com.auto;

import org.springframework.stereotype.Component;

import java.util.Random;

@Component
public class Man {
    private String name = "大壮";
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void qq(String toName){
        boolean b = new Random().nextBoolean();
        if(b) {
            throw new RuntimeException("聊天犯规了");
        }

        System.out.println(this.name + "在和[" + toName + "]聊QQ");
    }

    public String mm(){
        System.out.println(this.name + "在聊MM");
        return "很高兴";
    }

}

TestAop.java

package com.auto;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    private ClassPathXmlApplicationContext ac;

    @Test
    public void test(){
        Man man = ac.getBean(Man.class);
        man.qq("小美");
    }
    @Before
    public void init(){
        ac = new ClassPathXmlApplicationContext("spring-auto.xml");
    }
    @After
    public void destroy(){
        ac.close();
    }
}

结果

目标对象: com.auto.Man
目标对象方法参数: [小美]
目标对象的方法: qq

java.lang.RuntimeException: 聊天犯规了

对数据持久化的支持

alt

传统的执行效率最高
Spring JDBC抽象框架由四部分组成:datasource、support、core、object
数据源:描述数据库,数据库连接池,(池化技术)

常用的数据源:DBCP, C3p0, Druid, HikariCP(光)