spring中文參考手冊-核心技術 aop

spring aop,面向切面編程;java

1,用途:在日誌,登錄等重複無關業務邏輯的部分抽象出來;web

2,原理:java動態代理;spring

java.lang.reflect.Proxy;

 

切面:須要執行的代碼x(),好比插入的日誌代碼;數據庫

切入點:須要插入的位置,好比add()方法前面,後面....express

通知:一個普通的類->有特定功能的類: 編程

能夠經過a,繼承各類類;b,實現接口;3,註解,4,配置;session

 

通知: app

1,前置通知,在執行add()方法前執行;ide

2,後置通知,在執行add()方法正常執行後執行;url

3,環繞通知:能夠是前置|後置|異常時執行;

4,異常通知:程序異常才執行;

在applicationContext.xml配置aop

<bean id="logBefore" class="xxx.xxx.xxx">

</bean>

<!--將 切入點 和 通知 進行關聯-->

<aop:config>

  <aop:pointcut expression="execution(public void org.service.Student.addStudent(Student stu))">

  <aop:advisor advice-ref="logBefore" poincut-ref="pointcut"/>

</aop:config>

<!--將通知歸入springIOC容器-->
    <bean id="notice" class=""></bean>

    <aop:config>
        <!--切入點,須要執行代碼的地方-->
        <aop:pointcut id="pointcut" expression="execution(public * xx.xxx.function(paramtype))"/>
        <!--須要執行的代碼 -->
        <aop:advisor advice-ref="notice" pointcut-ref="pointcut"/>
    </aop:config>

說明:在任何addStudent方法前面,執行logBefore方法;

使用步驟:

1,通知類,普通實現通知接口;

2,業務類,業務方法:

3,配置: 將通知類,業務類歸入springIOC容器,xml中配置aop:config關聯切入點和通知類

 

環繞通知:(本質是攔截器)

public class LogAround implements MethodInterceptor {

    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object result=null;
        // 目標方法返回值
        try{
            //前置通知執行代碼
            result = methodInvocation.proceed();
            //後置通知執行代碼
        }catch (Exception e)        {
            //異常通知執行代碼
        }
        return result;
    }
}

配置:

<bean id="LogAround" class="com.maotu.control.LogAround"></bean>
    
    <aop:config>
        <!--切入點,須要執行代碼的地方-->
        <aop:pointcut id="pointcut2" expression="execution(public * xx.xxx.addStudent(paramtype))"/>
        <!--須要執行的代碼 -->
        <aop:advisor advice-ref="LogAround" pointcut-ref="pointcut2"/>
    </aop:config>

環繞通知能夠獲取目標方法的一切控制權:是否執行,執行前代碼,執行後代碼,執行返回值更改;

 

二,使用註解實現通知,aop

開啓註解:

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

1,設置掃描器:掃描註解所在的包

<context:component-scan base-package=""></context:component-scan>

2,配置: 將通知類,業務類歸入springIOC容器,xml中配置aop:config關聯切入點和通知

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component("logAroundAnno")
@Aspect
public class LogAroundAnno {

    @Before("execution(public * addStudent(..))") //屬性:定義切點
    public void myBefore(JoinPoint jp)
    {
        System.out.println("基於註解的前置通知,目標對象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName()+",參數列表:"+ Arrays.toString(jp.getArgs())+";");
    }

    @AfterReturning(pointcut = "execution(public * addStudent(..))",returning = "returnValue") //屬性:定義切點
    public void myAfter(JoinPoint jp,Object returnValue)
    {
        System.out.println("基於註解的後置通知,目標對象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName()+",參數列表:"+ Arrays.toString(jp.getArgs())+";返回值:"+returnValue);
    }

    //只捕獲特定異常
    @AfterThrowing(pointcut = "execution(public * addStudent(..))",throwing="e")
    public void myException(JoinPoint jp,NullPointerException e){
        System.out.println("基於註解的異常通知: 只捕獲空指針異常:e "+e.getMessage());
    }

    @Around("execution(public * addStudent(..))") //環繞通知
    public void myAround(ProceedingJoinPoint jp){
        try{
            //前置通知
            jp.proceed();
            //後置通知
        }catch (Throwable e)
        {
            //異常通知
        }finally{
            //最終通知
        }
    }

    @After("execution(public * addStudent(..))")
    public void MyAfter(){
        System.out.println("基於註解的最終通知");
    }
}

 

 

 

例子:登錄驗證

環境:intelli idea 2018+java 1.8

1,新建spring boot工程:包含登錄頁面/login; 主頁/index

2,新建攔截器類:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("----登錄攔截器----");
        if(request.getSession().getAttribute("username")==null)
        {
            response.sendRedirect("/login");
            return  false;
        }
        return true;
    }
}

攔截器繼承:HandlerInterceptor ,重載PreHandle方法;若是session中沒有用戶名,則進入登錄頁面;

3,新建登錄適配器:

import com.maotu.gameagent.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootConfiguration
public class LoginAdapt implements WebMvcConfigurer{

    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login**");

    }
}

對全部url進行攔截,對登錄頁面不攔截;

3,請求映射:

@RequestMapping(value = "/login")
    public String login(HttpServletRequest request){
        String userName = request.getParameter("username");
        if(userName!=null)
        {
            request.getSession().setAttribute("username",userName);
            return  "/agent/index";
        }
        return "/login";
    }


    @RequestMapping("/logout")
    public String logout(HttpServletRequest request)
    {
        try {
            request.getSession().invalidate();
            request.logout();
        } catch (ServletException e) {
            e.printStackTrace();
        }
        return  "/login";
    }

登錄用戶,到數據庫中驗證後,session賦值;退出後清空session。

 

註解形式依賴注入:

1,自動裝配,根據類型

@Service("aaa")
@Autowired

2,自動裝配,根據名稱裝配,

@Repository("stuDao")

@Autowired
@Qualifier("stuDao")
private IstudentDao studentDao;
相關文章
相關標籤/搜索