亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

慕課網(wǎng)_《探秘Spring AOP》學(xué)習(xí)總結(jié)

Tony_Zby / 2674人閱讀

時(shí)間:2017年09月03日星期日
說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com
教學(xué)源碼:https://github.com/zccodere/s...
學(xué)習(xí)源碼:https://github.com/zccodere/s...

第一章:課程介紹 1-1 面向切面

課程章節(jié)

概覽
AOP使用
AOP原理
AOP開(kāi)源運(yùn)用
課程實(shí)戰(zhàn)
課程總結(jié)

面向切面編程是一種編程范式

編程范式概覽

面向過(guò)程編程
面向?qū)ο缶幊?面向函數(shù)編程(函數(shù)式編程)
事件驅(qū)動(dòng)編程(GUI開(kāi)發(fā)中比較常見(jiàn))
面向切面編程

AOP是什么

是一種編程范式,不是編程語(yǔ)言
解決特定問(wèn)題,不能解決所有問(wèn)題
是OOP的補(bǔ)充,不是替代

AOP的初衷

DRY:Don’t Repeat Yourself代碼重復(fù)性問(wèn)題
SOC:Separation of Concerns關(guān)注點(diǎn)分離
    -水平分離:展示層->服務(wù)層->持久層
    -垂直分離:模塊劃分(訂單、庫(kù)存等)
    -切面分離:分離功能性需求與非功能性需求

使用AOP的好處

集中處理某一關(guān)注點(diǎn)/橫切邏輯
可以很方便地添加/刪除關(guān)注點(diǎn)
侵入性少,增強(qiáng)代碼可讀性及可維護(hù)性

AOP的應(yīng)用場(chǎng)景

權(quán)限控制
緩存控制
事務(wù)控制
審計(jì)日志
性能監(jiān)控
分布式追蹤
異常處理

支持AOP的編程語(yǔ)言

Java
.NET
C/C++
Ruby
Python
PHP
…
1-2 簡(jiǎn)單案例

案例背景

產(chǎn)品管理的服務(wù)
產(chǎn)品添加、刪除的操作只能管理員才能進(jìn)行
普通實(shí)現(xiàn)VS AOP實(shí)現(xiàn)

創(chuàng)建一個(gè)名為springaopguide的maven項(xiàng)目pom如下

完成后的項(xiàng)目結(jié)構(gòu)如下

代碼編寫

1.編寫Product類

package com.myimooc.springaopguide.domain;

/**
 * @title 產(chǎn)品領(lǐng)域模型
 * @describe 產(chǎn)品實(shí)體對(duì)象
 * @author zc
 * @version 1.0 2017-09-03
 */
public class Product {
    
    private Long id;
    
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

2.編寫CurrentUserHolder類

package com.myimooc.springaopguide.security;

/**
 * @title 獲取用戶信息
 * @describe 模擬用戶的切換,將用戶信息存入當(dāng)前線程
 * @author zc
 * @version 1.0 2017-09-03
 */
public class CurrentUserHolder {
    
    private static final ThreadLocal holder = new ThreadLocal<>();

    public static String get(){
        return holder.get() == null ? "unkown" : holder.get();
    }
    
    public static void set(String user){
        holder.set(user);
    }
}

3.編寫AdminOnly類

package com.myimooc.springaopguide.security;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @title 管理員權(quán)限注解
 * @describe 被該注解聲明的方法需要管理員權(quán)限
 * @author zc
 * @version 1.0 2017-09-03
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AdminOnly {

}

4.編寫SecurityAspect類

package com.myimooc.springaopguide.security;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.myimooc.springaopguide.service.AuthService;

/**
 * @title 權(quán)限校驗(yàn)切面類
 * @describe 
 * @author zc
 * @version 1.0 2017-09-03
 */
// 聲明為一個(gè)切面
@Aspect
@Component
public class SecurityAspect {
    
    @Autowired
    private AuthService authService;
    
    // 使用要攔截標(biāo)注有AdminOnly的注解進(jìn)行操作
    @Pointcut("@annotation(AdminOnly)")
    public void adminOnly(){
        
    }
    
    @Before("adminOnly()")
    public void check(){
        authService.checkAccess();
    }
    
}

5.編寫AuthService類

package com.myimooc.springaopguide.service;

import java.util.Objects;

import org.springframework.stereotype.Service;

import com.myimooc.springaopguide.security.CurrentUserHolder;

/**
 * @title 權(quán)限校驗(yàn)類
 * @describe 對(duì)用戶權(quán)限進(jìn)行校驗(yàn)
 * @author zc
 * @version 1.0 2017-09-03
 */
@Service
public class AuthService {
    
    public void checkAccess(){
        String user = CurrentUserHolder.get();
        if(!Objects.equals("admin", user)){
            throw new RuntimeException("operation not allow");
        }
    }
    
}

6.編寫ProductService類

package com.myimooc.springaopguide.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.myimooc.springaopguide.domain.Product;

/**
 * @title 產(chǎn)品服務(wù)類
 * @describe 產(chǎn)品相關(guān)業(yè)務(wù)服務(wù)-傳統(tǒng)方式實(shí)現(xiàn)權(quán)限校驗(yàn)
 * @author zc
 * @version 1.0 2017-09-03
 */
@Service
public class ProductService {
    
    @Autowired
    private AuthService AuthService;
    
    public void insert(Product product){
        AuthService.checkAccess();
        System.out.println("insert product");
    }
    
    public void delete(Long id){
        AuthService.checkAccess();
        System.out.println("delete product");
    }
    
}

7.編寫ProductServiceAop類

package com.myimooc.springaopguide.service;

import org.springframework.stereotype.Service;

import com.myimooc.springaopguide.domain.Product;
import com.myimooc.springaopguide.security.AdminOnly;

/**
 * @title 產(chǎn)品服務(wù)類
 * @describe 產(chǎn)品相關(guān)業(yè)務(wù)服務(wù)-AOP方式實(shí)現(xiàn)權(quán)限校驗(yàn)
 * @author zc
 * @version 1.0 2017-09-03
 */
@Service
public class ProductServiceAop {
    
    @AdminOnly
    public void insert(Product product){
        System.out.println("insert product");
    }
    
    @AdminOnly
    public void delete(Long id){
        System.out.println("delete product");
    }
    
}

8.編寫AopGuideApplicationTests類

package com.myimooc.springaopguide;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.myimooc.springaopguide.security.CurrentUserHolder;
import com.myimooc.springaopguide.service.ProductService;
import com.myimooc.springaopguide.service.ProductServiceAop;

/**
 * @title 單元測(cè)試類
 * @describe 測(cè)試權(quán)限校驗(yàn)服務(wù)是否生效
 * @author zc
 * @version 1.0 2017-09-03
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class AopGuideApplicationTests {
    
    @Autowired
    private ProductService productService;
    
    @Test(expected = Exception.class)
    public void annoInsertTest(){
        CurrentUserHolder.set("tom");
        productService.delete(1L);
    }
    
    @Test
    public void adminInsertTest(){
        CurrentUserHolder.set("admin");
        productService.delete(1L);
    }
    
    @Autowired
    private ProductServiceAop productServiceAop;
    
    @Test(expected = Exception.class)
    public void annoInsertAopTest(){
        CurrentUserHolder.set("tom");
        productServiceAop.delete(1L);
    }
    
    @Test
    public void adminInsertAopTest(){
        CurrentUserHolder.set("admin");
        productServiceAop.delete(1L);
    }
    
}
第二章:使用詳解 2-1 本節(jié)內(nèi)容

Spring AOP使用方式

XML配置+Pointcut expression【不推薦使用方式】
注解方式+ Pointcut expression【推薦使用該方式】

Aspectj注解

@Aspect:用于聲明當(dāng)前類是一個(gè)切面
@Pointcut:用于描述在哪些類、哪些方法上執(zhí)行切面的代碼
Advice:描述想要在這些方法執(zhí)行的什么時(shí)機(jī)進(jìn)行攔截

本章內(nèi)容

Pointcut express:切面表達(dá)式
5種Advice:建言的五種細(xì)分怎么使用
2-2 切面表達(dá)式

切面表達(dá)式

1.designators(指示器)
    execution()
    描述通過(guò)什么樣的方式去匹配哪些類、哪些方法
2.wildcards(通配符)
    * .. +
    使用通配符進(jìn)行描述
3.operators(運(yùn)算符)
    && || !
    使用運(yùn)算符進(jìn)行多條件的判斷

Designators(指示器)

匹配方法 execution()
匹配注解 @target() @args() @within() @annotation()
匹配包/類型 @within()
匹配對(duì)象 this() bean() target()
匹配參數(shù) args()

Wildcards(通配符)

* 匹配任意數(shù)量的字符
+ 匹配指定類及其子類
.. 一般用于匹配任意參數(shù)的子包或參數(shù)

Operators(運(yùn)算符)

&& 與操作符
|| 或操作符
! 非操作符
2-3 匹配包類
    // 匹配 ProductServiceAop 類里面的所有方法
    @Pointcut("within(com.myimooc.springaopguide.service.ProductServiceAop)")
    public void matchType(){}
    
    // 匹配 com.myimooc.springaopguide.service 包及子包下所有類的方法
    @Pointcut("within(com.myimooc.springaopguide.service..*)")
    public void matchPackage(){}
2-4 匹配對(duì)象
    // 匹配AOP對(duì)象的目標(biāo)對(duì)象為指定類型的方法,即DemoDao的aop代理對(duì)象的方法
    @Pointcut("this(com.myimooc.springaopguide.dao.DemoDao)")
    public void testDemo(){}
    
    // 匹配實(shí)現(xiàn)IDao接口的目標(biāo)對(duì)象(而不是aop代理后的對(duì)象)的方法,這里即DemoDao的方法
    @Pointcut("target(com.myimooc.springaopguide.dao.IDao)")
    public void targetDemo(){}
    
    // 匹配所有以Service結(jié)尾的bean里面的方法
    @Pointcut("bean(*Service)")
    public void beanDemo(){}
2-5 匹配參數(shù)
    // 匹配任何以find開(kāi)頭而且只有一個(gè)Long參數(shù)的方法
    @Pointcut("execution(* *..find*(Long))")
    public void argsDemo1(){}
    
    // 匹配任何只有一個(gè)Long參數(shù)的方法
    @Pointcut("args(Long)")
    public void argsDemo2(){}
    
    // 匹配任何以find開(kāi)頭而且第一個(gè)參數(shù)為L(zhǎng)ong型的方法
    @Pointcut("execution(* *..find*(Long,..))")
    public void argsDemo3(){}
    
    // 匹配第一個(gè)參數(shù)為L(zhǎng)ong型的方法
    @Pointcut("args(Long,..))")
    public void argsDemo4(){}
2-6 匹配注解
    // 匹配方法標(biāo)注有AdminOnly的注解的方法
    @Pointcut("@annotation(com.myimooc.springaopguide.security.AdminOnly)")
    public void annoDemo(){}
    
    // 匹配標(biāo)注有Beta的類底下的方法,要求的annotation的RetentionPolicy級(jí)別為CLASS
    @Pointcut("@within(com.google.common.annotations.Beta)")
    public void annoWithDemo(){}
    
    // 匹配標(biāo)注有Repository的類底下的方法,要求的RetentionPolicy級(jí)別為RUNTIME
    @Pointcut("@target(org.springframework.stereotype.Repository)")
    public void annoTargetDemo(){}
    
    // 匹配傳入的參數(shù)類標(biāo)注有Repository注解的方法
    @Pointcut("@args(org.springframework.stereotype.Repository)")
    public void annoArgsDemo(){}
2-7 匹配方法

execution()格式

execution(
    modifier-pattern? // 修飾符匹配
    ret-type-pattern // 返回值匹配
    declaring-type-pattern? // 描述值包名
    name-pattern(param-pattern) // 方法名匹配(參數(shù)匹配)
    throws-pattern?// 拋出異常匹配
)

execution()實(shí)例

    // 匹配 使用public修飾符 任意返回值 在com.myimooc.springaopguide.service包及子下 
    // 以Service結(jié)尾的類 任意方法(任意參數(shù))
    @Pointcut("execution(public * com.myimooc.springaopguide.service..*Service.*(..))")
    public void matchCondition(){}
2-8 建言注解

5中Advice(建言)注解

@Before,前置通知
@After(finally),后置通知,方法執(zhí)行完之后
@AfterReturning,返回通知,成功執(zhí)行之后
@AfterThrowing,異常通知,拋出異常之后
@Around,環(huán)繞通知

5中Advice(建言)實(shí)例

    // 定義切點(diǎn),攔截使用NeedSecured注解修飾的方法
    @Pointcut("@within(com.myimooc.demo.security.NeedSecured)")
    public void annoTargetVsWithinDemo(){}
    
    // 使用NeedSecured注解修飾 且 在com.myimooc包下的方法
    @Before("annoTargetVsWithinDemo() && within(com.myimooc..*)")
    public void beforeDemo(){
        System.out.println("被攔截方法執(zhí)行之前執(zhí)行");
    }
    
    @After("annoTargetVsWithinDemo() && within(com.myimooc..*)")
    public void afterDemo(){
        System.out.println("被攔截方法執(zhí)行之后執(zhí)行");
    }
    
    @AfterReturning("annoTargetVsWithinDemo() && within(com.myimooc..*)")
    public void afterReturning(){
        System.out.println("代碼成功之后執(zhí)行");
    }
    
    @AfterThrowing("annoTargetVsWithinDemo() && within(com.myimooc..*)")
    public void afterThrowing(){
        System.out.println("代碼執(zhí)行拋出異常之后執(zhí)行");
    }
    
    @Around("annoTargetVsWithinDemo() && within(com.myimooc..*)")
    public Object aroundDemo(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("相當(dāng)于@Before");
        try{
            Object result = pjp.proceed(pjp.getArgs());
            System.out.println("相當(dāng)于@AfterReturning");
            return result;
        }catch (Throwable throwable) {
            System.out.println("相當(dāng)于@AfterThrowing");
            throw throwable;
        }finally {
            System.out.println("相當(dāng)于@After");
        }
    }

Advice中的參數(shù)及結(jié)果綁定

    @Before("annoTargetVsWithinDemo() && within(com.myimooc..*) && args(userId)")
    public void beforeWithArgs(JoinPoint joinPoint,Long userId){
        System.out.println("被攔截方法執(zhí)行之前執(zhí)行,args:"+userId);
    }
    
    @AfterReturning(value="annoTargetVsWithinDemo() && within(com.myimooc..*)",returning="returnValue")
    public void getResult(Object returnValue){
        if(returnValue != null){
            System.out.println("代碼成功之后執(zhí)行,result:"+returnValue);
        }
    }
第三章:實(shí)現(xiàn)原理 3-1 本節(jié)內(nèi)容

上節(jié)回顧

Pointcut expression的組成部分
各種designators的區(qū)別
5中advice及參數(shù)、結(jié)果綁定

實(shí)現(xiàn)原理

概述
設(shè)計(jì):代理模式、責(zé)任鏈模式
實(shí)現(xiàn):JDK實(shí)現(xiàn)、cglib實(shí)現(xiàn)
3-2 原理概述

原理概述:植入的時(shí)機(jī)

1.編譯期(AspectJ)
2.類加載時(shí)(Aspectj 5+)
3.運(yùn)行時(shí)(Spring AOP)【本節(jié)課講解內(nèi)容】

運(yùn)行時(shí)值入

運(yùn)行時(shí)織入是怎么實(shí)現(xiàn)的
從靜態(tài)代理到動(dòng)態(tài)代理
基于接口代理與基于繼承代理
3-3 代理模式

代理AOP對(duì)象

Caller:調(diào)用方
Proxy:AOP代理對(duì)象
Target:目標(biāo)對(duì)象

代理模式類圖

客戶端通過(guò)接口來(lái)引用目標(biāo)對(duì)象
代理對(duì)象把真正的方法委托目標(biāo)對(duì)象來(lái)執(zhí)行,自己執(zhí)行額外的邏輯

代碼編寫

1.編寫Subject類

package com.myimooc.myproxydemo.pattern;

/**
 * @title 代理對(duì)象接口
 * @describe
 * @author zc
 * @version 1.0 2017-09-13
 */
public interface Subject {
    
    void request();
    
}

2.編寫RealSubject類

package com.myimooc.myproxydemo.pattern;

/**
 * @title 目標(biāo)對(duì)象
 * @describe 實(shí)現(xiàn)了Subject接口
 * @author zc
 * @version 1.0 2017-09-13
 */
public class RealSubject implements Subject{

    @Override
    public void request() {
        System.out.println("real subject execute request");
    }
    
}

3.編寫Proxy類

package com.myimooc.myproxydemo.pattern;

/**
 * @title 代理對(duì)象
 * @describe 同樣也實(shí)現(xiàn)了Subject接口
 * @author zc
 * @version 1.0 2017-09-13
 */
public class Proxy implements Subject{
    
    // 需要引用目標(biāo)對(duì)象
    private RealSubject realSubject;

    // 強(qiáng)制必須傳入目標(biāo)對(duì)象
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        
        // 在目標(biāo)對(duì)象方法執(zhí)行之前做一些額外的事情
        System.out.println("before");
        
        try{
        
            // 代理對(duì)象不會(huì)做真實(shí)的業(yè)務(wù)邏輯,還是委托給真實(shí)的目標(biāo)對(duì)象執(zhí)行
            realSubject.request();
        }catch (Exception e) {
            System.out.println("ex:"+e.getMessage());
            throw e;
        }finally {
            
            // 在目標(biāo)對(duì)象方法執(zhí)行之后做一些額外的事情
            System.out.println("after");
        }
    }
}

4.編寫Client類

package com.myimooc.myproxydemo.pattern;

/**
 * @title 客戶端
 * @describe 測(cè)試代理模式
 * @author zc
 * @version 1.0 2017-09-13
 */
public class Client {

    public static void main(String[] args) {
        Subject subject = new Proxy(new RealSubject());
        subject.request();
    }

}
3-4 JDK代理

靜態(tài)代理與動(dòng)態(tài)代理

靜態(tài)代理的缺點(diǎn):每當(dāng)需要代理的方法越多的時(shí)候,重復(fù)的邏輯就越多
動(dòng)態(tài)代理的兩類實(shí)現(xiàn):基于接口代理與基于繼承代理
兩類實(shí)現(xiàn)的代表技術(shù):JDK代理與Cglib代理

JDK實(shí)現(xiàn)要點(diǎn)

類:java.lang.reflect.Proxy
接口:InvocationHandler
只能基于接口進(jìn)行動(dòng)態(tài)代理

代碼編寫

1.編寫JdkSubject類

package com.myimooc.myproxydemo.jdkimpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import com.myimooc.myproxydemo.pattern.RealSubject;

/**
 * @title 動(dòng)態(tài)代理類
 * @describe 相當(dāng)于AOP的aspect
 * @author zc
 * @version 1.0 2017-09-13
 */
public class JdkSubject implements InvocationHandler{
    
    // 同樣需要引入目標(biāo)對(duì)象
    private RealSubject realSubject;
    
    public JdkSubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
        // 在目標(biāo)對(duì)象方法執(zhí)行之前做一些額外的事情
        System.out.println("before");
        Object result = null;
        try{
            // 代理對(duì)象不會(huì)做真實(shí)的業(yè)務(wù)邏輯,還是委托給真實(shí)的目標(biāo)對(duì)象執(zhí)行
            result = method.invoke(realSubject, args);
        }catch (Exception e) {
            System.out.println("ex:"+e.getMessage());
            throw e;
        }finally {
            // 在目標(biāo)對(duì)象方法執(zhí)行之后做一些額外的事情
            System.out.println("after");
        }
        return result;
    }
}

2.編寫Client類

package com.myimooc.myproxydemo.jdkimpl;

import java.lang.reflect.Proxy;

import com.myimooc.myproxydemo.pattern.RealSubject;
import com.myimooc.myproxydemo.pattern.Subject;

/**
 * @title 動(dòng)態(tài)代理類
 * @describe JDK實(shí)現(xiàn)動(dòng)態(tài)代理測(cè)試類
 * @author zc
 * @version 1.0 2017-09-13
 */
public class Client {
    
    public static void main(String[] args) {
        Subject subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(),
            new Class[]{Subject.class}, new JdkSubject(new RealSubject()));
        subject.request();
    }
    
}
3-5 JDK解析

JDK代理源碼解析

Proxy.newProxyInstance(首先,調(diào)用該方法)
getProxyClass0、ProxyClassFactory、ProxyGenerator(然后,分別調(diào)用方法,生成字節(jié)碼)
newInstance(最后,利用反射根據(jù)字節(jié)碼生成實(shí)例)
3-6 Cglib代理

代碼編寫

1.編寫DemoMethodInterceptor類

package com.myimooc.myproxydemo.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * @title 需要植入的代碼類
 * @describe 需要實(shí)現(xiàn)MethodInterceptorj接口
 * @author zc
 * @version 1.0 2017-09-13
 */
public class DemoMethodInterceptor implements MethodInterceptor{

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before in cglib");
        
        Object result = null;
        try{
            // 代理類調(diào)用父類的方法
            proxy.invokeSuper(obj, args);
        }catch (Exception e) {
            System.out.println("ex:"+e.getMessage());
            throw e;
        }finally {
            // 在目標(biāo)對(duì)象方法執(zhí)行之后做一些額外的事情
            System.out.println("after in cglib");
        }
        return result;
    }
}

2.編寫Client類

package com.myimooc.myproxydemo.cglib;

import com.myimooc.myproxydemo.pattern.RealSubject;
import com.myimooc.myproxydemo.pattern.Subject;

import net.sf.cglib.proxy.Enhancer;

/**
 * @title 動(dòng)態(tài)代理類
 * @describe Cglib實(shí)現(xiàn)動(dòng)態(tài)代理測(cè)試類
 * @author zc
 * @version 1.0 2017-09-13
 */
public class Client {
    
    public static void main(String[] args) {
        // 實(shí)例化Enhancer對(duì)象
        Enhancer enhancer = new Enhancer();
        // 設(shè)置需要代理的對(duì)象
        enhancer.setSuperclass(RealSubject.class);
        // 設(shè)置需要植入的代碼
        enhancer.setCallback(new DemoMethodInterceptor());
        // 生成代理類
        Subject subject = (Subject)enhancer.create();
        subject.request();
    }
}

JDK與Cglib代理對(duì)比

JDK只能針對(duì)有接口的類的接口方法進(jìn)行動(dòng)態(tài)代理
Cglib基于繼承來(lái)實(shí)現(xiàn)代理,無(wú)法對(duì)static、final類進(jìn)行代理
Cglib基于繼承來(lái)實(shí)現(xiàn)代理,無(wú)法對(duì)private、static方法進(jìn)行代理
3-7 Spring選擇

Spring創(chuàng)建代理bean時(shí)序圖

SpringAOP對(duì)兩種實(shí)現(xiàn)的選擇

如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,則默認(rèn)采用JDK動(dòng)態(tài)代理
如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)接口,則采用Cglib進(jìn)行動(dòng)態(tài)代理
如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,但設(shè)置強(qiáng)制cglib代理,則使用cglib代理
在SpringBoot中,通過(guò)@EnableAspectJAutoProxy(proxyTargetClass=true)設(shè)置
3-8 鏈?zhǔn)秸{(diào)用

當(dāng)多個(gè)AOP作用到同一個(gè)目標(biāo)對(duì)象時(shí),采用責(zé)任鏈模式

責(zé)任鏈模式類圖

代碼編寫

1.編寫Handler類

package com.myimooc.myproxydemo.chain;

/**
 * @title 責(zé)任鏈模式
 * @describe 抽象接口
 * @author zc
 * @version 1.0 2017-09-13
 */
public abstract class Handler {
    
    // 后繼Handler,是否有類進(jìn)行處理
    private Handler sucessor;
    
    // 對(duì)外暴露
    public void execute(){
        handleProcess();
        if(sucessor != null){
            sucessor.execute();
        }
    }
    
    // 由子類實(shí)現(xiàn)
    protected abstract void handleProcess();
    
    public Handler getSucessor() {
        return sucessor;
    }

    public void setSucessor(Handler sucessor) {
        this.sucessor = sucessor;
    }
    
}

2.編寫Client類

package com.myimooc.myproxydemo.chain;

/**
 * @title 責(zé)任鏈模式
 * @describe 測(cè)試類
 * @author zc
 * @version 1.0 2017-09-13
 */
public class Client {
    
    static class HandlerA extends Handler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by a");
        }
    }
    static class HandlerB extends Handler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by b");
        }
    }
    static class HandlerC extends Handler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by c");
        }
    }
    
    public static void main(String[] args) {
        HandlerA handlerA = new HandlerA();
        HandlerB HandlerB = new HandlerB();
        HandlerC HandlerC = new HandlerC();
        // 設(shè)置鏈接關(guān)系
        handlerA.setSucessor(HandlerB);
        HandlerB.setSucessor(HandlerC);
        
        handlerA.execute();
    }
}

3.編寫Chain類

package com.myimooc.myproxydemo.chain;

import java.util.List;

/**
 * @title 責(zé)任鏈模式
 * @describe 封裝鏈?zhǔn)疥P(guān)系
 * @author zc
 * @version 1.0 2017-09-13
 */
public class Chain {
    
    private List handlers;
    
    private int index = 0;
    
    public Chain(List handlers){
        this.handlers = handlers;
    }
    
    public void proceed(){
        if(index >= handlers.size()){
            return;
        }
        handlers.get(index++).execute(this);
    }
}

4.編寫ChainHandler類

package com.myimooc.myproxydemo.chain;

/**
 * @title 責(zé)任鏈模式
 * @describe 對(duì)Handler進(jìn)行封裝
 * @author zc
 * @version 1.0 2017-09-13
 */
public abstract class ChainHandler {
    
    public void execute(Chain chain){
        handleProcess();
        chain.proceed();
    }
    
    // 由子類實(shí)現(xiàn)
    protected abstract void handleProcess();
    
}

5.編寫ChainClient類

package com.myimooc.myproxydemo.chain;

import java.util.Arrays;
import java.util.List;

/**
 * @title 責(zé)任鏈模式
 * @describe 有順序的鏈?zhǔn)秸{(diào)用測(cè)試類
 * @author zc
 * @version 1.0 2017-09-13
 */
public class ChainClient {
    
    static class ChainHandlerA extends ChainHandler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by a");
        }
    }
    static class ChainHandlerB extends ChainHandler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by b");
        }
    }
    static class ChainHandlerC extends ChainHandler{
        @Override
        protected void handleProcess() {
            System.out.println("handle by c");
        }
    }
    
    public static void main(String[] args) {
        // 聲明鏈?zhǔn)秸{(diào)用順序
        List handlers = Arrays.asList(
            new ChainHandlerA(),
            new ChainHandlerB(),
            new ChainHandlerC()
        );
        
        Chain chain = new Chain(handlers);
        chain.proceed();
    }
}
第四章:代碼解讀 4-1 本節(jié)內(nèi)容

上節(jié)回顧

靜態(tài)代理與動(dòng)態(tài)代理
JDK代理與Cglib代理區(qū)別及局限
代理模式與責(zé)任鏈模式

Spring AOP在開(kāi)源項(xiàng)目里面的應(yīng)用:三個(gè)例子

事務(wù):@Transactional:Spring如何利用Transaction進(jìn)行事務(wù)控制
安全:@PreAuthorize:Spring Security如何利用PreAuthorize進(jìn)行安全控制
緩存:@Cacheable:Spring Cache如何利用Cacheable進(jìn)行緩存控制

通過(guò)案例來(lái)講解,源碼可到我的github地址查看

第五章:實(shí)戰(zhàn)案例 5-1 案例背景

實(shí)戰(zhàn)案例背景

商家產(chǎn)品管理系統(tǒng)
記錄產(chǎn)品修改的操作記錄
什么人在什么時(shí)間修改了哪些產(chǎn)品的哪些字段修改為什么值

實(shí)現(xiàn)思路

利用aspect去攔截增刪改方法
利用反射獲取對(duì)象的新舊值
利用@Around的advice去記錄操作記錄
5-2 案例實(shí)現(xiàn)

創(chuàng)建名為mydatalog的maven項(xiàng)目pom如下


  4.0.0

  com.myimooc
  mydatalog
  0.0.1-SNAPSHOT
  jar

  mydatalog
  http://maven.apache.org


        org.springframework.boot
        spring-boot-starter-parent
        1.5.2.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-aop
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

        
            mysql
            mysql-connector-java
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            commons-beanutils
            commons-beanutils
        
        
            com.alibaba
            fastjson
            1.2.36
        
        
    
    

完成后的項(xiàng)目結(jié)構(gòu)圖如下

受篇幅限制,源碼請(qǐng)到我的github地址查看

第六章:課程總結(jié) 6-1 課程總結(jié)

要點(diǎn)清單

AOP的適用范圍及優(yōu)劣勢(shì)
AOP的概念及Spring切面表達(dá)式
AOP的實(shí)現(xiàn)原理及運(yùn)用

使用SpringAOP的注意事項(xiàng)

不宜把重要的業(yè)務(wù)邏輯放到AOP中處理
無(wú)法攔截static、final、private方法
無(wú)法攔截內(nèi)部方法調(diào)用

課程小結(jié)

合理利用面向切面編程提高代碼質(zhì)量
掌握SpringAOP概念及實(shí)現(xiàn)原理
了解AOP的優(yōu)缺點(diǎn)及SpringAOP的使用局限

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/70475.html

相關(guān)文章

  • 課網(wǎng)_Spring入門篇》學(xué)習(xí)總結(jié)

    摘要:入門篇學(xué)習(xí)總結(jié)時(shí)間年月日星期三說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。主要的功能是日志記錄,性能統(tǒng)計(jì),安全控制,事務(wù)處理,異常處理等等。 《Spring入門篇》學(xué)習(xí)總結(jié) 時(shí)間:2017年1月18日星期三說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個(gè)人學(xué)習(xí)源碼:https://git...

    Ververica 評(píng)論0 收藏0
  • 課網(wǎng)_SpringBoot進(jìn)階之Web進(jìn)階》學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期日說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。慕課網(wǎng)教學(xué)示例源碼個(gè)人學(xué)習(xí)源碼第一章課程介紹課程介紹本課程緊接著小時(shí)學(xué)會(huì)課程,請(qǐng)先看入門課。異常返回通知在連接點(diǎn)拋出異常后執(zhí)行。 時(shí)間:2017年3月19日星期日說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個(gè)人學(xué)習(xí)源碼:htt...

    lifefriend_007 評(píng)論0 收藏0
  • 課網(wǎng)_Spring事務(wù)管理》學(xué)習(xí)總結(jié)

    摘要:事務(wù)管理學(xué)習(xí)總結(jié)時(shí)間年月日星期二說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。一致性一致性指事務(wù)前后數(shù)據(jù)的完整性必須保持一致。聲明式事務(wù)管理基于的方式很少使用需要為每個(gè)進(jìn)行事務(wù)管理的類,配置一個(gè)進(jìn)行增強(qiáng)。 《Spring事務(wù)管理》學(xué)習(xí)總結(jié) 時(shí)間:2017年2月7日星期二說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com/教學(xué)示例源碼:https://github.com...

    Airy 評(píng)論0 收藏0
  • 課網(wǎng)_《使用Google Guice實(shí)現(xiàn)依賴注入》學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期六說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。慕課網(wǎng)教學(xué)源碼學(xué)習(xí)源碼第一章課程介紹課程簡(jiǎn)介是啥讀音是輕量級(jí)的依賴注入框架說(shuō)明一個(gè)的框架需要有基礎(chǔ)什么是剝離注入輕量級(jí)代碼少易維護(hù)性能優(yōu)異,跟比較。 時(shí)間:2017年10月14日星期六說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com 教學(xué)源碼:https://github.com/zccodere/s......

    2450184176 評(píng)論0 收藏0
  • 課網(wǎng)_《基于SSH實(shí)現(xiàn)員工管理系統(tǒng)之框架整合篇》學(xué)習(xí)總結(jié)

    時(shí)間:2017年08月16日星期三說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 課程介紹 課程目錄 1.ssh知識(shí)點(diǎn)回顧 2.搭建ssm開(kāi)發(fā)環(huán)境 3.struts2整合spring 4.spring整合hibernate 5.案例:使用ssh框架開(kāi)發(fā)...

    icattlecoder 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<