Spring(八)jdk動态代理(AOP簡單實作)
Spring(九)CGLIB位元組碼增強
這兩篇文章寫了兩種方式的手動生成代理。我們應該如何使用spring自動生成代理呢
spring編寫代理(半自動)
我們首先使用spring來模拟我們自己生成的代理步驟即半自動
目标類
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
切面類
切面類中确定通知,需要實作不同接口,接口就是規範,進而就确定方法名稱。
采用“環繞通知” MethodInterceptor
public class MyAspect implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("前方法");
Object obj=null;
//執行目标類
obj=mi.proceed();
System.out.println("後方法");
return
spring配置
在建立代理類時,使用工廠bean factorybean 底層調用getObject傳回特殊bean
proxyFactoryBean用于建立代理工廠bean 生成特殊代理對象。
interfaces : 确定接口們
通過可以設定多個值
隻有一個值時,可以使用value=””
target : 确定目标類
interceptorNames : 通知 切面類的名稱,類型String[],如果設定一個值 value=””
在上兩篇文章中我們分别使用了jdk動态代理和cglib動态代理
在spring中我們可以通過設定
<property name="optimize" value="true"></property>
強制使用cglib 而在不聲明optimize時
spring底層将判斷目标類是否有接口,如果沒有接口 使用cglib位元組碼增強,否則使用jdk動态代理。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 建立目标類 -->
<bean id="userServiceId" class="com.scx.autoproxy.test.UserServiceImpl"></bean>
<!-- 建立切面類 -->
<bean id="myAspectId" class="com.scx.autoproxy.test.MyAspect"></bean>
<!-- 建立代理類-->
<bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.scx.autoproxy.test.UserService"></property>
<property name="target" ref="userServiceId"></property>
<property name="interceptorNames" value="myAspectId"></property>
</bean>
</beans>
測試
public void testProxy(){
String xmlPath="com/scx/autoproxy/test/applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
UserService userService=(UserService) applicationContext.getBean("proxyServiceId");
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
運作結果:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CM0EDM0QTOzUmM0ImY3MWZyYzXyUDOwATM1AzLchDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
spring編寫代理(全自動)
全自動和半自動相比較在于xml配置檔案的代理類的編寫
在半自動中,我們是通過模拟jdk動态代理的方式生成代理。在全自動中
使用aop命名空間實作。
spring配置
<?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: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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 建立目标類 -->
<bean id="userServiceId" class="com.scx.autoproxy.test.copy.UserServiceImpl"></bean>
<!-- 建立切面類(通知) -->
<bean id="myAspectId" class="com.scx.autoproxy.test.copy.MyAspect"></bean>
<!-- 建立代理類-->
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution(* com.scx.autoproxy.test.copy.*.*(..))" id="myPointCut"/>
<aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/>
</aop:config>
</beans>
execution(* com.scx.autoproxy.test.copy.*.*(..))
/*
解釋如下:
execution選擇方法
* 傳回值任意
com.scx.autoproxy.test.copy 包名
* 類名任意
* 方法名任意
.. 參數任意
*/
測試
public void testProxy(){
String xmlPath="com/scx/autoproxy/test/copy/applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
UserService userService=(UserService) applicationContext.getBean("userServiceId");
userService.addUser();
userService.updateUser();
userService.deleteUser();
}