偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Spring一個(gè)強(qiáng)大便捷的代理工廠類,你用過(guò)嗎?

開(kāi)發(fā) 前端
ProxyFactoryBean與其他Spring FactoryBean實(shí)現(xiàn)一樣,引入了一個(gè)間接級(jí)別。如果定義了名為pack的ProxyFactoryBean,那么引用pack的對(duì)象看不到ProxyFactoryBean實(shí)例本身,而是由ProxyFactoryBean#getObject()方法實(shí)現(xiàn)創(chuàng)建的對(duì)象。

環(huán)境:Spring6.1.2

1. 簡(jiǎn)介

在Spring框架中,AOP(面向切面編程)是一種強(qiáng)大的編程范式,它允許開(kāi)發(fā)者在不修改原有代碼的情況下,為程序添加額外的功能,如日志記錄、事務(wù)管理、安全控制等。

實(shí)際開(kāi)發(fā)中常用實(shí)現(xiàn)AOP配置方式:

  • 基于XML

在早期的Spring版本中,開(kāi)發(fā)者常常使用XML配置文件來(lái)定義切面、通知和目標(biāo)對(duì)象之間的關(guān)聯(lián)。通過(guò)配置<aop:config>、<aop:aspect>、<aop:before>等標(biāo)簽,可以輕松地實(shí)現(xiàn)AOP的各種功能。如下示例:

<aop:config>
  <aop:aspect id="myAspect" ref="aBean">
    <aop:pointcut id="businessService"
      expression="execution(* com.pack.service.*.*(..))"/>
    <aop:before pointcut-ref="businessService" method="monitor"/>
  </aop:aspect>
</aop:config>
  • 基于注解

通過(guò)在切面類和方法上使用如@Aspect、@Before、@After等注解,可以更加簡(jiǎn)潔地定義AOP的相關(guān)配置。這種方式不僅減少了XML配置的工作量,還使得代碼更加清晰易讀。如下示例:

@Component
@Aspect
public class LogAspect {
  @Pointcut("execution(* save(..))")
  private void logPc() {}
  @Around("logPc()")
  public Object process(ProceedingJoinPoint pjp) throws Throwable {
    Object ret = null ;
    System.out.println("before log...") ;
    ret = pjp.proceed() ;
    System.out.println("after log...") ;
    return ret ;
  }
}

以上是Spring提供的2中方式來(lái)聲明AOP配置方式。但如果你需要一種更加靈活和可配置性,那么Spring還提供了一個(gè)非常方便強(qiáng)大的ProxyFactoryBean類,該類特別適合那些需要更多自定義和控制的場(chǎng)景,例如當(dāng)你需要為特定的Bean創(chuàng)建代理,或者需要在不修改原始代碼的情況下為現(xiàn)有類添加額外的功能時(shí)。

2. 實(shí)戰(zhàn)案例

ProxyFactoryBean與其他Spring FactoryBean實(shí)現(xiàn)一樣,引入了一個(gè)間接級(jí)別。如果定義了名為pack的ProxyFactoryBean,那么引用pack的對(duì)象看不到ProxyFactoryBean實(shí)例本身,而是由ProxyFactoryBean#getObject()方法實(shí)現(xiàn)創(chuàng)建的對(duì)象。此方法創(chuàng)建一個(gè)AOP代理,用于包裝目標(biāo)對(duì)象。

2.1 屬性配置

ProxyFactoryBean提供了很多屬性,讓你可以靈活的配置代理對(duì)象。該對(duì)象繼承了ProxyConfig,一些關(guān)鍵的屬性是由ProxyConfig定義。

  • proxyTargetClass:如果要代理目標(biāo)類,而不是目標(biāo)類的接口,則為true。如果此屬性值設(shè)置為true,則會(huì)創(chuàng)建CGLIB代理。
  • optimize:控制是否對(duì)通過(guò)CGLIB創(chuàng)建的代理應(yīng)用積極的優(yōu)化。除非完全理解相關(guān)AOP代理如何處理優(yōu)化,否則不應(yīng)該輕松地使用此設(shè)置。目前僅用于CGLIB代理。它對(duì)JDK動(dòng)態(tài)代理沒(méi)有影響。
  • frozen:如果代理配置被凍結(jié),則不再允許更改該配置。此屬性的默認(rèn)值為false,因此允許更改(例如添加額外的通知)。
  • exposeProxy:確定是否應(yīng)在ThreadLocal中公開(kāi)當(dāng)前代理,以便目標(biāo)可以訪問(wèn)它。如果目標(biāo)需要獲取代理,并且exposeProxy屬性設(shè)置為true,則該目標(biāo)可以使用AoPontext.currentProxy()方法獲取代理對(duì)象。
  • proxyInterface:字符串接口名稱的數(shù)組。
  • interceptorNames:要應(yīng)用的Advisor、攔截器或其他建議名稱的字符串?dāng)?shù)組。

接下來(lái)將從2方面介紹ProxyFactoryBean的使用,代理接口與代理類。2.2 代理接口

要通過(guò)ProxyFactoryBean創(chuàng)建代理,你至少需要涉及到下面幾點(diǎn)(類):

  • 需要被代理的目標(biāo)bean類。
  • 一個(gè)Advisor或者Advice,增強(qiáng)部分。
  • 指定要代理的接口。

如下示例:

public interface ICommonDAO {
  void save() ;
}
@Component("commonDAOTarget")
public class CommonDAOImpl implements ICommonDAO {
  @Override
  public void save() {
    System.out.println("save operator...") ;
  }
}
@Component
public class LogInterceptor implements MethodInterceptor {
  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {
    System.out.println("before log...") ;
    Object ret = invocation.proceed() ;
    System.out.println("after  log...") ;
    return ret ;
  }
}


@Configuration
public class AppConfig {
  @Bean
  // 由于上面已經(jīng)定義了CommonDAOImpl,而這里的FactoryBean#getObject返回的
  // 也是一個(gè)實(shí)現(xiàn)了ICommonDAO接口的對(duì)象,所以需要加上@Primary
  @Primary
  ProxyFactoryBean commonDAO(@Qualifier("commonDAOTarget") CommonDAOImpl commonDAOTarget) throws Exception {
    ProxyFactoryBean proxy = new ProxyFactoryBean() ;
    proxy.setProxyInterfaces(new Class<?>[] {ICommonDAO.class}) ;
    proxy.setTarget(commonDAOTarget) ;
    proxy.setInterceptorNames("logInterceptor") ;
    return proxy ;
  }
}

測(cè)試

ICommonDAO dao = context.getBean(ICommonDAO.class) ;
dao.save() ;
// 輸出
before log...
save operator...
after  log...

2.3 代理類

如果我們的目標(biāo)沒(méi)有實(shí)現(xiàn)接口,那么我們只能通過(guò)CGLIB進(jìn)行代理,通過(guò)設(shè)置proxyTargetClass屬性為true。CGLIB代理通過(guò)在運(yùn)行時(shí)生成目標(biāo)類的子類來(lái)工作。Spring將這個(gè)生成的子類配置為將方法調(diào)用委托給原始目標(biāo)。如下示例:

@Component("commonDAOTarget")
public class CommonDAO {
  public void save() {
    System.out.println("save operator...") ;
  }
}
@Bean
@Primary
ProxyFactoryBean commonDAO(@Qualifier("commonDAOTarget") CommonDAO commonDAOTarget) throws Exception {
  ProxyFactoryBean proxy = new ProxyFactoryBean() ;
  proxy.setTarget(commonDAOTarget) ;
  proxy.setInterceptorNames("logInterceptor") ;
  // 代理類,可以不設(shè)置
  proxy.setProxyTargetClass(true) ;
  return proxy ;
}

查看最終的CommonDAO是否是通過(guò)CGLIB代理

CommonDAO dao = context.getBean(CommonDAO.class) ;
System.out.println(dao.getClass()) ;

輸出結(jié)果

class com.pack.aop.create.ProxyFactoryBeanTest2$CommonDAO$$SpringCGLIB$$1

CGLIB代理通過(guò)在運(yùn)行時(shí)生成目標(biāo)類的子類來(lái)工作。但需要注意以下事項(xiàng):

  • final 類不能被代理,因?yàn)樗鼈儾荒鼙粩U(kuò)展。
  • final方法無(wú)法提供增強(qiáng),因?yàn)樗鼈儾荒鼙桓采w。
  • 不能增強(qiáng)private方法,因?yàn)樗鼈儾荒鼙恢貙憽?/li>
  • 不可見(jiàn)的方法,通常是來(lái)自不同包的父類中的包私有方法,不能被增強(qiáng),因?yàn)樗鼈儗?shí)際上是私有的。

2.4 模糊匹配攔截器

在上面配置攔截器時(shí),我們都是指定的具體攔截器,其實(shí)我們還可以使用通配符,指定攔截器。如下示例:

@Component("global_log")
public class LogInterceptor implements MethodInterceptor {
}
@Component("global_auth")
public class AuthInterceptor implements MethodInterceptor {
}
// ProxyFactoryBena配置
ProxyFactoryBean commonDAO() throws Exception {
  ProxyFactoryBean proxy = new ProxyFactoryBean() ;
  // 注意:這里的通配符必須是最后,你不能放到其它位置
  proxy.setInterceptorNames("global_*") ;
  return proxy ;
}

以上ProxyFactoryBean在初始化時(shí),會(huì)自動(dòng)查找容器中beanName以global_開(kāi)頭的所有Bean對(duì)象。

責(zé)任編輯:武曉燕 來(lái)源: Spring全家桶實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2023-09-13 09:20:00

日志配置Spring

2025-01-07 09:16:16

2009-07-27 14:19:01

Eclipse JDT

2011-03-24 09:34:41

SPRING

2024-05-09 08:08:32

SpringBinderJava

2021-12-31 10:40:48

JarbootJavaGitHub

2009-10-16 09:03:36

Visual Stud

2022-03-03 08:02:55

數(shù)據(jù)集成平臺(tái)

2024-01-09 08:20:05

2025-01-09 06:00:00

Checkmate監(jiān)控系統(tǒng)開(kāi)源

2020-08-16 10:58:20

Pandaspython開(kāi)發(fā)

2022-05-27 09:02:31

Openbase開(kāi)源前端

2023-09-09 12:23:24

函數(shù)式接口程序

2022-11-29 07:33:15

JavaLombokRecord

2015-03-30 12:20:07

DemoStoryboard

2024-02-19 08:26:59

wxPython界面庫(kù)開(kāi)發(fā)

2020-10-13 14:54:11

機(jī)器學(xué)習(xí)技術(shù)工具

2025-03-28 00:44:00

JavaScript屬性算法

2023-09-12 08:19:48

接口Controller線程

2020-11-15 18:20:44

GnuCash開(kāi)源會(huì)計(jì)軟
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)