Java AOP動(dòng)態(tài)代理詳細(xì)介紹
1.IOC與AOP概念
IOC:控制反轉(zhuǎn),把對(duì)象創(chuàng)建和對(duì)象之間的調(diào)用過程,交給Spring進(jìn)行管理。使用IOC的目的是為了降低耦合度。
AOP:面向切面編程,通過預(yù)編譯方式和運(yùn)行期間動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。AOP是OOP的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中的一個(gè)重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。AOP的底層實(shí)現(xiàn)是基于動(dòng)態(tài)代理(實(shí)現(xiàn)方式是當(dāng)切入接口時(shí),使用JDK原生動(dòng)態(tài)代理;當(dāng)切入普通方法時(shí),使用cglib動(dòng)態(tài)代理)。
2.為何使用動(dòng)態(tài)代理
隨著業(yè)務(wù)的不斷擴(kuò)展:
(1)日志功能:如果日志代碼修改,需要修改多處。
(2)校驗(yàn)功能:如果多處需要校驗(yàn),需要修改多處。
這時(shí)就需要使用動(dòng)態(tài)代理來解決問題,動(dòng)態(tài)代理的實(shí)現(xiàn)方式有兩種:
[1]JDK原生動(dòng)態(tài)代理:缺點(diǎn)是必須基于接口完成
[2]cglib動(dòng)態(tài)代理:他可以不用基于接口完成
2.1 JDK原生動(dòng)態(tài)代理
?
2.1.1 MathService接口類
public interface MathService {
//+
public Double add(double a,double b);
//-
public Double sub(double a,double b);
//*
public Double mul(double a,double b);
///
public Double div(double a,double b);
}2.1.2 MathServiceImpl實(shí)現(xiàn)接口類
public class MathServiceImpl implements MathService{
@Override
public Double add(double a, double b) {
Double result=a+b;
return result;
}
@Override
public Double sub(double a, double b) {
Double result=a-b;
return result;
}
@Override
public Double mul(double a, double b) {
Double result=a*b;
return result;
}
@Override
public Double div(double a, double b) {
Double result=a/b;
return result;
}
}2.1.3 ProxyFactory動(dòng)態(tài)代理工廠
public class ProxyFactory {
//被代理對(duì)象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//獲取代理對(duì)象
public Object getProxy(){
/**
* ClassLoader loader, 被代理對(duì)象的類加載器
* Class<?>[] interfaces, 被代理對(duì)象實(shí)現(xiàn)的接口
* InvocationHandler h: 當(dāng)代理對(duì)象執(zhí)行被代理的方法時(shí),會(huì)觸發(fā)該對(duì)象中的invoke功能
*/
ClassLoader loader=target.getClass().getClassLoader();
Class<?>[] interfaces=target.getClass().getInterfaces();
InvocationHandler h=new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//可以加上需要的非業(yè)務(wù)代碼
//method.getName()獲取方法名
// Arrays.asList(args)獲取輸入值
System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
//method:表示代理對(duì)象要代理的方法
//invoke:回調(diào)該函數(shù)
//args:方法需要的參數(shù)
Object result = method.invoke(target, args);//代理對(duì)象回調(diào)該方法
return result;
}
};
//先寫此處方法,才可找到上述三個(gè)方法填寫方式
Object o = Proxy.newProxyInstance(loader, interfaces, h);
return o;
}
}2.1.4 測(cè)試類
public class Test01 {
public static void main(String[] args) {
MathServiceImpl target=new MathServiceImpl();
ProxyFactory proxyFactory=new ProxyFactory(target);
MathService proxy = (MathService) proxyFactory.getProxy();
Double add = proxy.add(15.0, 5.0);
System.out.println(add);
}
}2.2 cglib動(dòng)態(tài)代理
?
2.2.1 MathServiceImpl類
public class MathServiceImpl{
public Double add(double a, double b) {
Double result=a+b;
return result;
}
public Double sub(double a, double b) {
Double result=a-b;
return result;
}
public Double mul(double a, double b) {
Double result=a*b;
return result;
}
public Double div(double a, double b) {
Double result=a/b;
return result;
}
}2.2.2 ProxyFactory動(dòng)態(tài)代理工廠
注意:
(1)引入cglib的jar包.
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
(2)創(chuàng)建一個(gè)代理類工廠并實(shí)現(xiàn)接口MethodInterceptor
public class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//獲取代理對(duì)象
public Object getProxy(){
Enhancer enhancer=new Enhancer();
//指定被代理對(duì)象的父類
enhancer.setSuperclass(target.getClass());
//指定回調(diào)類
enhancer.setCallback(this);
//創(chuàng)建代理對(duì)象
return enhancer.create();
}
//當(dāng)代理對(duì)象執(zhí)行代理方法時(shí)觸發(fā)的方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// System.out.println("before++++++++++++++++++++");
// Object result = method.invoke(target, args);
//可以加上需要的非業(yè)務(wù)代碼
//method.getName()獲取方法名
// Arrays.asList(args)獲取輸入值
System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
//method:表示代理對(duì)象要代理的方法
//invoke:回調(diào)該函數(shù)
//args:方法需要的參數(shù)
Object result = method.invoke(target, args);//代理對(duì)象回調(diào)該方法
return result;
}
}2.2.3 測(cè)試類
public class Test01 {
public static void main(String[] args) {
MathServiceImpl target=new MathServiceImpl();
ProxyFactory proxyFactory=new ProxyFactory(target);
MathServiceImpl proxy = (MathServiceImpl) proxyFactory.getProxy();
Double add = proxy.add(1, 2);
System.out.println(add);
}
}3.AOP動(dòng)態(tài)代理

3.1 添加對(duì)應(yīng)依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>3.2 配置spring.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:context="http://www.springframework.org/schema/context"
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/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--包掃描-->
<context:component-scan base-package="com.qy151wd.proxy.proxy.aop"/>
<!--開啟aop注解-->
<aop:aspectj-autoproxy/>
</beans>3.3 MathService接口類
public interface MathService {
public Double add(double a, double b);
public Double sub(double a, double b);
public Double mul(double a, double b);
public Double div(double a, double b);
}3.4 MathServiceImpl實(shí)現(xiàn)接口類
@Service
public class MathServiceImpl implements MathService {
@Override
public Double add(double a, double b) {
Double result=a+b;
return result;
}
@Override
public Double sub(double a, double b) {
Double result=a-b;
return result;
}
@Override
public Double mul(double a, double b) {
Double result=a*b;
return result;
}
@Override
public Double div(double a, double b) {
Double result=a/b;
return result;
}
}3.5 LogAspect類
@Service //若是使用@component也可以
@Aspect //表示該類為切面類
public class LogAspect {
//任意返回類型 aop包下的所有類都有切面日志 使用通配符
//第一個(gè)*:修飾符和返回值類型
//第二個(gè)*:所有類
//第三個(gè)*:所有方法
@Before("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")
public void before(){
System.out.println("方法執(zhí)行前的日志");
}
@After("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))") //總會(huì)被執(zhí)行,不管有沒有異常
public void after(){
System.out.println("方法執(zhí)行后的日志");
}
@AfterReturning("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//只有碰到return后才會(huì)執(zhí)行
public void afterReturning(){
System.out.println("碰到return后執(zhí)行");
}
@AfterThrowing("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//異常通知
public void afterThrowing(){
System.out.println("出現(xiàn)異常了");
}
}3.6 測(cè)試類
public class Test01 {
public static void main(String[] args) {
//從spring容器中獲取
ApplicationContext app=new ClassPathXmlApplicationContext("spring.xml");
MathService mathService = (MathService) app.getBean("mathServiceImpl");
Double add = mathService.add(10, 5);
System.out.println(add);
}
}到此這篇關(guān)于Java AOP動(dòng)態(tài)代理詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Java AOP動(dòng)態(tài)代理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Cloud?中自定義外部化擴(kuò)展機(jī)制原理及實(shí)戰(zhàn)記錄
這篇文章主要介紹了Spring?Cloud?中自定義外部化擴(kuò)展機(jī)制原理及實(shí)戰(zhàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
JAVA正則表達(dá)式及字符串的替換與分解相關(guān)知識(shí)總結(jié)
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí)總結(jié),文章圍繞著JAVA正則表達(dá)式及字符串的替換與分解展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
全面詳解Maven打包及其相關(guān)插件和高級(jí)特性
這篇文章主要為大家介紹了Maven打包及其相關(guān)插件和高級(jí)特性的全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
SpringBoot項(xiàng)目將mybatis升級(jí)為mybatis-plus的方法
本文主要介紹了SpringBoot項(xiàng)目將mybatis升級(jí)為mybatis-plus的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
springboot中使用undertow踩坑記(最新推薦)
這篇文章主要介紹了springboot中使用undertow踩坑記,springboot內(nèi)置類web中間件,將web服務(wù)器管理權(quán)交給了容器,本文分步驟給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08

