Java中l(wèi)ambda表達(dá)式實(shí)現(xiàn)aop切面功能
背景:最近項(xiàng)目中涉及到自定義線程池中子線程獲取父線程的traceId,這個(gè)數(shù)據(jù)的傳遞過程可以用lamdba表達(dá)式進(jìn)行封裝實(shí)現(xiàn)的。這讓我想到spring容器的三級(jí)緩存。其中的一個(gè)緩存singletonFactories就是存放的lambda表達(dá)式的。
// 緩存的聲明 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// lambda作為參數(shù)調(diào)用addSingletonFactory方法
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
// addSingletonFactory方法
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 緩存中添加lambda
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}一些業(yè)務(wù)邏輯可以通過lambda表達(dá)式進(jìn)行封裝,就可以當(dāng)作一個(gè)參數(shù)一樣進(jìn)行傳遞,然后在需要的時(shí)候進(jìn)行執(zhí)行。但是它的強(qiáng)大并不止于此,還可以當(dāng)作aop切面進(jìn)行使用。通過一個(gè)demo進(jìn)行展示
lambda表達(dá)式實(shí)現(xiàn)切面功能
定義一個(gè)函數(shù)式接口
@FunctionalInterface
public interface DemoInterface {
void Demo();
}創(chuàng)建兩個(gè)實(shí)現(xiàn)類
public class DemoSonOne implements DemoInterface{
public DemoSonOne(Integer age) {
this.age = age;
}
private Integer age;
public Integer getAge() {
return age;
}
// 重寫接口
@Override
public void Demo() {
System.out.println("I'm DemoSonOne, My age is " + age);
}
}public class DemoSonTwo implements DemoInterface{
public DemoSonTwo(String name) {
this.name = name;
}
private String name;
public String getName() {
return name;
}
// 實(shí)現(xiàn)接口
@Override
public void Demo() {
System.out.println("I'm DemoSonOne, My name is " + name);
}
}客戶端
public class DemoMain { // lambda表達(dá)式進(jìn)行封裝 public static DemoInterface wrap(final DemoInterface demoInterface){ return () -> { System.out.println("Demo方法要執(zhí)行了"); demoInterface.Demo(); System.out.println("Demo方法要執(zhí)行完了"); }; } public static void main(String[] args) { DemoSonOne demoSonOne = new DemoSonOne(18); DemoSonTwo demoSonTwo = new DemoSonTwo("haha"); demoSonOne.Demo(); System.out.println("-----------------------"); demoSonTwo.Demo(); System.out.println("-----------------------"); DemoInterface wrapOne = wrap(demoSonOne); DemoInterface wrapTwo = wrap(demoSonTwo); wrapOne.Demo(); System.out.println("-----------------------"); wrapTwo.Demo(); }}public class DemoMain {
// lambda表達(dá)式進(jìn)行封裝
public static DemoInterface wrap(final DemoInterface demoInterface){
return () -> {
System.out.println("Demo方法要執(zhí)行了");
demoInterface.Demo();
System.out.println("Demo方法要執(zhí)行完了");
};
}
public static void main(String[] args) {
DemoSonOne demoSonOne = new DemoSonOne(18);
DemoSonTwo demoSonTwo = new DemoSonTwo("haha");
demoSonOne.Demo();
System.out.println("-----------------------");
demoSonTwo.Demo();
System.out.println("-----------------------");
DemoInterface wrapOne = wrap(demoSonOne);
DemoInterface wrapTwo = wrap(demoSonTwo);
wrapOne.Demo();
System.out.println("-----------------------");
wrapTwo.Demo();
}
}執(zhí)行結(jié)果

執(zhí)行結(jié)果如下,可以看到經(jīng)過wrap方法封裝后的DemoInterface接口對(duì)象,執(zhí)行過程都會(huì)走lamdba中的代碼。給人一種aop的感覺
缺點(diǎn)
經(jīng)過wrap方法返回的對(duì)象都是DemoInterface類型的,它是接口類型,如果在某種特定的情況下能夠確定它是由某個(gè)子類類型實(shí)力化得到的,想要強(qiáng)轉(zhuǎn)回去,然后獲取子類獨(dú)有的屬性,這種情況下會(huì)報(bào)錯(cuò)。
public static void main(String[] args) {
DemoSonOne demoSonOne = new DemoSonOne(18);
// 經(jīng)過lambda封裝,得到接口類型
DemoInterface wrapOne = wrap(demoSonOne);
wrapOne.Demo();
// 由接口類型轉(zhuǎn)換為現(xiàn)實(shí)類類型
DemoSonOne wrapOne1 = (DemoSonOne) wrapOne;
Integer age = wrapOne1.getAge();
System.out.println(age);
}
錯(cuò)誤結(jié)果顯示如下:
Exception in thread "main" java.lang.ClassCastException: class functionInterface.DemoMain$$Lambda$14/0x0000000800066840 cannot be cast to class functionInterface.DemoSonOne (functionInterface.DemoMain$$Lambda$14/0x0000000800066840 and functionInterface.DemoSonOne are in unnamed module of loader 'app')
at functionInterface.DemoMain.main(DemoMain.java:26)
由此可見該方法進(jìn)行封裝有好處,也有壞處,所以要謹(jǐn)慎使用。
到此這篇關(guān)于Java中l(wèi)ambda表達(dá)式實(shí)現(xiàn)aop切面功能的文章就介紹到這了,更多相關(guān)lambda表達(dá)式實(shí)現(xiàn)aop切面內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis圖文并茂講解注解開發(fā)多對(duì)多查詢
這篇文章主要介紹了SpringBoot中Mybatis注解多對(duì)多查詢的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
JavaWeb禁止瀏覽器緩存當(dāng)前Web頁(yè)面的方法
所謂瀏覽器緩存,是指當(dāng)?shù)谝淮卧L問網(wǎng)頁(yè)時(shí),瀏覽器會(huì)將這些網(wǎng)頁(yè)緩存到本地,當(dāng)下一次再訪問這些被緩存的網(wǎng)頁(yè)時(shí),瀏覽器就會(huì)直接從本地讀取這些網(wǎng)頁(yè)的內(nèi)容,而無需再?gòu)木W(wǎng)絡(luò)上獲取2017-11-11
java操作Redis緩存設(shè)置過期時(shí)間的方法
這篇文章主要介紹了java操作Redis緩存設(shè)置過期時(shí)間的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Spring?Boot中@Import三種使用方式實(shí)例詳解
這篇文章主要介紹了Spring?Boot中@Import三種使用方式,主要有引入普通類,引入importSelector的實(shí)現(xiàn)類及引入importBeanDefinitionRegister的實(shí)現(xiàn)類,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2022-11-11
SpringBoot整合Log4j2實(shí)現(xiàn)自定義日志打印失效的原因及解決
本文給大家介紹了關(guān)于SpringBoot項(xiàng)目整合Log4j2實(shí)現(xiàn)自定義日志打印失效原因及解決辦法,主要的原因是因?yàn)镾pringBoot的logback包的存在,文中通過圖文給大家了詳細(xì)解決方法,需要的朋友可以參考下2024-01-01
Java Lock鎖多線程中實(shí)現(xiàn)流水線任務(wù)
這篇文章主要介紹了Java Lock鎖多線程中實(shí)現(xiàn)流水線任務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
springboot2.5.6集成RabbitMq實(shí)現(xiàn)Topic主題模式(推薦)
這篇文章主要介紹了springboot2.5.6集成RabbitMq實(shí)現(xiàn)Topic主題模式(推薦),pom.xml引入依賴和常量類創(chuàng)建,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-11-11

