Spring AOP2020-09-29
一、spring(春天)核心之 aop(重點)
aop:Aspect Oriented Programming 面向切面程式設計 ,是一種思想。
oop: Object Orinted programming 物件導向程式設計 ,是一種思想。
AOP可以說是OOP的補充和完善。OOP引入封裝、繼承、多型等概念來建立一種物件層次結構,在類的層次上進行抽取。不過OOP允許開發者定義縱向的關係,但並不適合定義橫向的關係,例如日誌功能。日誌程式碼往往橫向地散佈在所有物件層次中,而與它對應的物件的核心功能毫無關係對於其他型別的程式碼,如安全性、異常處理和透明的持續性也都是如此,這種散佈在各處的無關的程式碼被稱為橫切(cross cutting),在OOP設計中,它導致了大量程式碼的重複,而不利於各個模組的重用。
AOP技術恰恰相反,它利用一種稱為"橫切"的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其命名為"Aspect",即切面。所謂"切面",簡單說就是那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組之間的耦合度,並有利於未來的可操作性和可維護性。
總結:
oop:縱向抽取
好處:
1)提高可重用性
2)提高可擴充套件和可維護
3)多型
aop:橫向向抽取
好處:
1)提高可重用性
2)提高可擴充套件和可維護
二、aop怎麼玩?
1.aop底層原理:動態代理技術
2. jdk動態代理和cglib動態代理
代理========>經紀人、中介
三、動態代理(重點)
黑客入侵
1)jdk黑客: 只能入侵實現介面的物件。 針對介面實現類
jdk介面:InvocationHandler
==>JDK動態代理技術
## jdk動態代理(只能動態代理有介面的類)
1、先建立一個介面
public interface UserDao {
int add(int a, int b);
}
2、實現介面
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
System.out.println("呼叫UserDaoImpl的add方法");
return a+b;
}
}
3、建立JdkHk實現InvocationHandler介面
public class JdkHk implements InvocationHandler{
//目標物件
private Object target;
public JdkHk() {
}
//有參構造,傳入引數
public JdkHk(UserDao userDao) {
this.target=userDao;
}
/**
* 黑客類入侵的方法
* proxy:代理物件
* method:入侵的目標的方法
* args:入侵的目標的方法的引數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("1、鑑權成功");
//幹壞事
args[0]=11;
args[1]=22;
//呼叫目標方法
Object result = method.invoke(target, args);
System.out.println("2、儲存處理日誌成功");
return result;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
4、測試類
public class Test01 {
public static void main(String[] args) {
//客戶端---呼叫目標類(UserDaoImpl)的目標方法add方法
// UserDao userDao = new UserDaoImpl();
// int result = userDao.add(3, 5);
// System.out.println("result==>:"+result);
//目標物件
UserDao targert = new UserDaoImpl();
//黑客物件
JdkHk jdkHk = new JdkHk(targert);
//代理物件
/*
* loader 類載入器
* ClassLoader.getSystemClassLoader() 獲取當前程式的類載入器
* interfaces 目標的實現的介面class
* h invocationHandler物件--黑客物件
* 位元組碼拼接技術
*/
UserDao userDao = (UserDao) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {UserDao.class}, jdkHk);
//客戶端
int result = userDao.add(45, 5);
System.out.println("result==>"+result);
}
}
2)spring黑客:針對類(aspect包—spring提供的)
aopalliance: MethodInteceptor 當類實現介面內部用的jdk黑客 如果類沒有實現介面 使用cglib動態代理
==>可以使用JDK動態代理(實現介面類) 也可以使用Cglib動態代理(類或實現介面類)
1、建立一個不實現介面的類
public class UserDaoImpl2 {
public int add(int a, int b) {
System.out.println("呼叫UserDaoImpl的add方法");
return a+b;
}
}
2、建立springHk類實現MethodInteceptor 介面
public class SpringHk implements MethodInterceptor{
/*
* invocation : 目標物件的目標方法
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("1.鑑權");
//呼叫目標方法
Object result = invocation.proceed();
System.out.println("1.日誌留痕");
return result;
}
}
3、測試類(這裡通過依賴注入的方式來建立物件,需要配置檔案spring-beans.xml)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-beans.xml")
public class SpringHkTest {
@Autowired//預設按型別注入,通過@Qualifier修改為按名稱注入
@Qualifier("userDaoProxy")
private UserDaoImpl2 userDao;//cglib
@Autowired//預設按型別注入,通過@Qualifier修改為按名稱注入
@Qualifier("userDaoProxy2")
private UserDaoImpl userDao2;//cglib
@Test
public void test01() {
//目標沒有實現介面
System.out.println(userDao.add(3, 5));
System.out.println(userDao2.add(3, 5));
}
}
spring-beans.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--1.目標物件 -->
<bean id="userDao" class="com.cc.dao.impl.UserDaoImpl2"></bean>
<bean id="userDaoInter" class="com.cc.dao.impl.UserDaoImpl"></bean>
<!--2.spring 黑客物件 -->
<bean id="springHk" class="com.cc.proxy.SpringHk">
</bean>
<bean id="jdkHk" class="com.cc.proxy.JdkHk">
<!-- <constructor-arg name="target" ref="userDaoInter"></constructor-arg> -->
</bean>
<!--3.代理物件 :Cglib動態代理 -->
<bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 3.1 目標物件 -->
<property name="target" ref="userDao"></property>
<!-- 3.2 spring 黑客物件 -->
<property name="interceptorNames">
<array>
<value>springHk</value>
</array>
</property>
</bean>
<!-- JDK動態代理 -->
<bean id="userDaoProxy2" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 3.2 目標物件 -->
<property name="proxyInterfaces" value="com.cc.dao.UserDao"></property>
<!-- 3.1 目標物件 -->
<property name="target" ref="userDaoInter"></property>
<!-- 3.2 spring 黑客物件 -->
<property name="interceptorNames">
<array>
<value>springHk</value>
</array>
</property>
</bean>
</beans>
四、aop的術語
1、橫切關注點
對哪些方法進行攔截,攔截後怎麼處理,這些關注點稱之為橫切關注點
2、切面(aspect)
類是對物體特徵的抽象,切面就是對橫切關注點的抽象
3、連線點(joinpoint)
被攔截到的點,因為Spring只支援方法型別的連線點,所以在Spring中連線點指的就是被攔截到的方法,實際上連線點還可以是欄位或者構造器
4、切入點(pointcut)
對連線點進行攔截的定義
5、通知(advice)
所謂通知指的就是指攔截到連線點之後要執行的程式碼,通知分為前置、後置、異常、最終、環繞通知五類
6、目標物件
代理的目標物件
7、植入(weave)
將切面應用到目標物件並導致代理物件建立的過程
8、引入(introduction)
在不修改程式碼的前提下,引入可以在執行期為類動態地新增一些方法或欄位
aop:將物件的目標方法通過動態代理技術進行植入增強,從而達到
增強方法的目的
相關文章
- spring、spring MVC、spring BootMVCSpring Boot
- Spring系列之初識Spring Spring概述Spring
- Spring框架 - Spring和Spring框架組成Spring框架
- Spring Boot/Spring MVCSpring BootMVC
- Learn Spring – Spring DAOSpring
- Spring Boot —— Spring SecuritySpring Boot
- Spring Boot整合Spring BatchSpring BootBAT
- Spring Boot整合Spring SecuritySpring Boot
- Spring Boot整合Spring AopSpring Boot
- Spring系列—Spring入門Spring
- 理解Spring(一):Spring 與 IoCSpring
- Spring Boot:整合Spring Data JPASpring Boot
- Spring Boot:Spring Boot配置MybatisSpring BootMyBatis
- 「Spring認證」Spring 框架概述Spring框架
- Spring---Spring專題(二)Spring
- spring:spring與mybatis的整合SpringMyBatis
- spring框架——Spring框架簡介Spring框架
- Spring review--Spring框架概述SpringView框架
- Spring review--Spring框架搭建SpringView框架
- spring-boot+spring-session整合SpringbootSession
- SPRING-spring註解整理Spring
- SpringSpring
- Spring框架系列(2) - Spring簡單例子引入Spring要點Spring框架單例
- spring-boot 整合 spring-securitySpringboot
- 【Spring系列】- Spring迴圈依賴Spring
- 【Spring】Spring後置處理器Spring
- spring-boot 整合 spring-sessionSpringbootSession
- Spring Boot (十三): Spring Boot 小技巧Spring Boot
- spring學習:spring原始碼_BeanDefinitionSpring原始碼Bean
- Spring security(四)-spring boot +spring security簡訊認證+redis整合Spring BootRedis
- Spring、Spring Boot和TestNG測試指南 – 使用Spring Testing工具Spring Boot
- 如何從Spring Security 5遷移到Spring Security 6/Spring Boot 3Spring Boot
- 【spring】迴圈依賴 Java Vs SpringSpringJava
- Spring Cloud Stream事件路由 - spring.ioSpringCloud事件路由
- Spring入門(一):建立Spring專案Spring
- Spring IOC 一——Spring容器裝配BeanSpringBean
- Spring 系列(二):Spring MVC的父子容器SpringMVC
- Spring原始碼剖析6:Spring AOP概述Spring原始碼