Spring中的代理(proxy)模式


代理模式主要有兩種:靜態代理和動態代理
 代理模式 代理模式是常用的 Java 設計模式,它的特征是代理類與委托類有同樣的接口,代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事后處理消息等。代理類與委托類之間通常會存在關聯關系,一個代理類的對象與一個委托類的對象關聯, 代理 類的對象本身並不真正實現服務, 而是通過調用委托類的對象的相關方法, 來提供特定的服務. 按照代理類的創建時期,代理類可分為兩種。


 1.靜態代理類: 由程序員創建或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類 的.class 文件就已經存在了。

靜態代理類 如下:
StudentImpl 類是代理類,

public class StudentImpl implements IStudentServiceDAO {
    StudentServiceImpl service;
    StudentImpl(StudentServiceImpl service) {
        this.service = service;
    }
    @Override
    public void save(Student stu) {
        System.out.println("開啟事務");
        service.save(stu);
        System.out.println("提交事務");
    }
}

StudentServiceImpl 類是委托類,

public class StudentServiceImpl implements IStudentServiceDAO {
    @Override
    public void save(Student stu) {
        System.out.println("調用dao層保存方法");
    }
}  

這兩個類都實現了 HelloService 接口.

其中 StudentServiceImpl 類是 IStudentServiceDAO 接口的真正實現者,
而 StudentImpl 類是通過調用 StudentServiceImpl 類的相關方法來提供特定服務的.

StudentImpl 類的 save()方法會分別調用被代理的 StudentServiceImpl 對象的 save()方法,並且在方法調用前后都會執行一些簡單的打印操作。 由此可見,代理類可以為委托類預處理消息、把消息轉發給委托類和事后處理消息等。

測試類代碼:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class StaticProxyTest {
    @Autowired
    @Qualifier("servicetran")
    IStudentServiceDAO service;
    @Test
    public void testStaticProxy() {
        service.save(new Student("ZhangSan", 18));
    }
}

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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
   <--id="service"的類為委托類---> <bean id="service" class="com.gxxy.spring_05proxy.static1.StudentServiceImpl"></bean>
   <--id="servicetran"的類為代理類-->
<bean id="servicetran" class="com.gxxy.spring_05proxy.static1.StudentImpl"> <constructor-arg name="service" ref="service"></constructor-arg> </bean> </beans>

類的源代碼是由程序員編寫的,在程序運行前,它的.class 文件就已經存在了,這種代理類稱為靜態代理類。
 2.動態代理類:在程序運行時,運用反射機制動態創建而成。

動態代理類的字節碼在程序運行時由Java 反射機制動態生成,無需程序員手工編寫它的源代碼.動態代理類不僅簡化了編程工作,而且提高了 軟件系統的可擴展性,因為Java反射機制可以生成任意類型的動態代理類.
java.lang.reflect 包中的 Proxy 類和 InvocationHandler 接口提供了生成動態代理類的能力。
Proxy 類提供了創建動態代理類及其實例的靜態方法。

①:接口(interface)/InvocationHandler

代理類:實現 InvocationHandler 接口  注意: InvocationHandler 是 import java.lang.reflect.InvocationHandler包中的;

package com.gxxy.spring_05proxy.dynamic.interfaces;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyDynamicInvocationHandler implements InvocationHandler {
    private IStudentServiceDAO service;
    ProxyDynamicInvocationHandler(IStudentServiceDAO service) {
        this.service = service;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Begin");
        System.out.println("save");
        System.out.println("commit");
        System.out.println("-------"+method.getName());
        return method.invoke(service, args);
    }
}

委托類:(實現IStudentServiceDAO  接口,接口中只有save()方法)

public class StudentServiceImpl implements IStudentServiceDAO {
    @Override
    public void save(Student stu) {
        System.out.println("調用dao層保存方法");
    }
}

測試類:

package com.gxxy.spring_05proxy.dynamic.interfaces;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class DynamicProxyTest {
    @Autowired
    IStudentServiceDAO service;
    @Test
    public void testStaticProxy() {
        ClassLoader loader = IStudentServiceDAO.class.getClassLoader();
        Class<?>[] interfaces = new Class<?>[] { IStudentServiceDAO.class };
        InvocationHandler h = new ProxyDynamicInvocationHandler(service);
        IStudentServiceDAO newProxyInstance = (IStudentServiceDAO) Proxy.newProxyInstance(loader, interfaces, h);
        newProxyInstance.save(new Student("ZhangSan",18));
    }
}

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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean  id="service" class="com.gxxy.spring_05proxy.dynamic.StudentServiceImpl"></bean>
</beans>

②:繼承(inherit)/Enhancer

代理類:實現 InvocationHandler 接口  注意: InvocationHandler 是 import org.springframework.cglib.proxy.InvocationHandler 包中的;

 

package com.gxxy.spring_05proxy.dynamic.inherit;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.InvocationHandler;
public class ProxyDynamicInvocationHandler implements InvocationHandler {
    private Object service;
    ProxyDynamicInvocationHandler(StudentServiceImpl service) {
        this.service = service;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Begin");
        System.out.println("save");
        System.out.println("commit");
        System.out.println("-------" + method.getName());
        return method.invoke(service, args);
    }
}

 

委托類:StudentServiceImpl

package com.gxxy.spring_05proxy.dynamic.inherit;
public class StudentServiceImpl {
    public void save(Student stu) {
        System.out.println("調用dao層保存方法");
    }
}

測試類:

package com.gxxy.spring_05proxy.dynamic.inherit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class DynamicinheritProxyTest {
    @Autowired
    StudentServiceImpl service;
    @Test
    public void testStaticProxy() {
        ClassLoader loader = StudentServiceImpl.class.getClassLoader();
        InvocationHandler handle = new ProxyDynamicInvocationHandler(service);
        Enhancer hancer = new Enhancer();
        hancer.setClassLoader(loader);
        hancer.setSuperclass(StudentServiceImpl.class);
        hancer.setCallback(handle);
        StudentServiceImpl create = (StudentServiceImpl) hancer.create();
        create.save(new Student("Jack", 18));
    }
}

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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean  id="service" class="com.gxxy.spring_05proxy.dynamic.inherit.StudentServiceImpl"></bean>
</beans>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM