Spring --11.Spring的AOP入門
1、AOP 概述
AOP概述
AOP為Aspect Oriented Programming的縮寫。意為面向切面程式設計。通過預編譯方式和老實巴交行期動態代理實現程式
功能的統一維護的一種技術。AOP是OOP的延續、AOP:面向切面程式設計。AOP是OOP的擴充套件和延伸,解決OOP開發遇到問題。
AOP作用
在不修改原始碼的情況下、可以實現功能的增強
傳統程式碼是縱向體系程式碼複用、
AOP是橫向抽取機制、基於代理思想、對原來目標物件、建立代理物件、在不修改原物件程式碼情況下、通過對代理物件、
呼叫增強功能的程式碼、從而對原有業務方法進行增強
AOP應用場景
場景一:記錄日誌
場景二:監控方法執行時間
場景三:許可權抑制
場景四:快取優化(第一呼叫查詢資料庫、將查詢結果放入記憶體物件、第二次呼叫、直接從記憶體物件返回、不需要查詢資料庫)
場景五:事務管理(呼叫方法前開啟事務、呼叫方法後提交關閉事務)
AOP原理
Spring中AOP有二種實現方式:
(1)、JDK動態代理 、只能對實現了介面的類產生代理。
(2)、Cglib動態代理、(類似於Javassist第三方代理技術):對沒有實現介面的類產生代理物件。生成子類物件
2、Spring的AOP底層實現
(1)、JDK動態代理
UserDao.java介面
package com.day03.dao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:48 2018/11/11
*/
public interface UserDao {
public abstract void save();
public abstract void delete();
public abstract void update();
public abstract void select();
}
UserDaoImpl.java實現類
package com.day03.dao.Impl; import com.day03.dao.UserDao; /** * @ Author :ShaoWei Sun. * @ Date :Created in 21:48 2018/11/11 */ public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("save方法。。。。。。。。。。。"); } @Override public void delete() { System.out.println("delete方法。。。。。。。。。。。"); } @Override public void update() { System.out.println("update......................"); } @Override public void select() { System.out.println("select..........................."); } }
代理類:TestProxy.java
package com.day03.test;
import com.day03.dao.UserDao;
import org.junit.Test;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;
import java.lang.reflect.Method;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 11:47 2018/11/11
*/
public class TestProxy implements InvocationHandler {
private UserDao userDao;
public TestProxy(UserDao userDao) {
this.userDao = userDao;
}
@Test
public UserDao createProxy(){
UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(),this);
return proxy;
}
//回撥方法
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if ("save".equals(method.getName())){
//增強
System.out.println("增強許可權。。。。。");
return method.invoke(userDao,objects);
}
return method.invoke(userDao,objects);
}
}
testDemo.java測試類
package com.day03.test;
import com.day03.dao.Impl.UserDaoImpl;
import com.day03.dao.UserDao;
import org.junit.Test;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:51 2018/11/11
*/
public class TestDemo {
@Test
public void test1() {
UserDao userDao = new UserDaoImpl();
UserDao proxy = new TestProxy(userDao).createProxy();
proxy.save();
//userDao.save();
proxy.delete();
proxy.update();
proxy.select();
}
}
(2)、Cglib動態代理
UserDao.java介面
package com.day03.dao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:48 2018/11/11
*/
public interface UserDao {
public abstract void save();
public abstract void delete();
public abstract void update();
public abstract void select();
}
UserDaoImpl.java實現類
package com.day03.dao.Impl;
import com.day03.dao.UserDao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:48 2018/11/11
*/
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("save方法。。。。。。。。。。。");
}
@Override
public void delete() {
System.out.println("delete方法。。。。。。。。。。。");
}
@Override
public void update() {
System.out.println("update......................");
}
@Override
public void select() {
System.out.println("select...........................");
}
}
CglibProxy.java動態代理
package com.day03.test;
import com.day03.dao.UserDao;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:57 2018/11/12
*/
public class CglibProxy implements MethodInterceptor {
private UserDao userDao;
public CglibProxy(UserDao userDao) {
this.userDao = userDao;
}
public UserDao createProxy(){
//1、建立cglib的核心類物件
Enhancer enhancer = new Enhancer();
//2、設定父類
enhancer.setSuperclass(userDao.getClass());
//3、設定回撥(類似InvocationHandler物件)
enhancer.setCallback(this);
//4、建立代理物件
UserDao proxy = (UserDao) enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//判斷方法是否為save;
if ("save".equals(method.getName())){
//增強
System.out.println("許可權核驗。。。。。。。。。。。");
return methodProxy.invokeSuper(proxy,objects);
}
return methodProxy.invokeSuper(proxy,objects);
}
}
TestDemo.java測試類
package com.day03.test;
import com.day03.dao.Impl.UserDaoImpl;
import com.day03.dao.UserDao;
import org.junit.Test;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:51 2018/11/11
*/
public class TestDemo {
@Test
public void test1() {
UserDao userDao = new UserDaoImpl();
UserDao proxy = new CglibProxy(userDao).createProxy();
proxy.save();
//userDao.save();
proxy.delete();
proxy.update();
proxy.select();
}
}
3、AOP相關術語
Joinpoint (連線點)
連線點是指那些被攔截到的點、在spring中、這些點指的是方法、spring只支援方法型別的連線點
Pointcut(切入點)
指的是我們要對哪些Joinpoint進行攔截
Advice(通知/增強)
通知是指攔截到Joinpoint之後所要做的事情就是通知、通知分為前置通知、後置通知、異常通知、最終通知、環繞通知(切面要完成的功能)
Introduction(引介)
引介是一種特殊的通知、在不修改程式碼的前提下、Introduction可以在執行期為類動態地新增一些方法或Field
Target(目標物件)
代理的目標物件
Weaving(織入)
是指把增強應用到目標物件來建立新的代理物件的過程、spring採用動態代理織入、而Asp
Proxy(代理)
一個類被AOP織入增強後、就產生一個結果代理類
Aspect(切面)
是切入紅開和通知(引介)的結合