天天看點

Spring(十)spring編寫代理(aop程式設計)

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();
    }      

運作結果:

Spring(十)spring編寫代理(aop程式設計)

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();
    }      

運作結果: