java靜態署理(jdk與cglib)具體解析。本站提示廣大學習愛好者:(java靜態署理(jdk與cglib)具體解析)文章只能為提供參考,不一定能成為您想要的結果。以下是java靜態署理(jdk與cglib)具體解析正文
JAVA的靜態署理
署理形式
署理形式是經常使用的java設計形式,他的特點是署理類與拜托類有異樣的接口,署理類重要擔任為拜托類預處置新聞、過濾新聞、把新聞轉發給拜托類,和過後處置新聞等。署理類與拜托類之間平日會存在聯系關系關系,一個署理類的對象與一個拜托類的對象聯系關系,署理類的對象自己其實不真正完成辦事,而是經由過程挪用拜托類的對象的相干辦法,來供給特定的辦事。
依照署理的創立時代,署理類可以分為兩種。
靜態署理:由法式員創立或特定對象主動生成源代碼,再對其編譯。在法式運轉前,署理類的.class文件就曾經存在了。
靜態署理:在法式運轉時,應用反射機制靜態創立而成。
起首看一下靜態署理:
1、Count.java
package net.battier.dao;
/**
* 界說一個賬戶接口
*
* @author Administrator
*
*/
public interface Count {
// 檢查賬戶辦法
public void queryCount();
// 修正賬戶辦法
public void updateCount();
}
2、CountImpl.java
package net.battier.dao.impl;
import net.battier.dao.Count;
/**
* 拜托類(包括營業邏輯)
*
* @author Administrator
*
*/
public class CountImpl implements Count {
@Override
public void queryCount() {
System.out.println("檢查賬戶辦法...");
}
@Override
public void updateCount() {
System.out.println("修正賬戶辦法...");
}
}
CountProxy.java
package net.battier.dao.impl;
import net.battier.dao.Count;
/**
* 這是一個署理類(加強CountImpl完成類)
*
* @author Administrator
*
*/
public class CountProxy implements Count {
private CountImpl countImpl;
/**
* 籠罩默許結構器
*
* @param countImpl
*/
public CountProxy(CountImpl countImpl) {
this.countImpl = countImpl;
}
@Override
public void queryCount() {
System.out.println("事務處置之前");
// 挪用拜托類的辦法;
countImpl.queryCount();
System.out.println("事務處置以後");
}
@Override
public void updateCount() {
System.out.println("事務處置之前");
// 挪用拜托類的辦法;
countImpl.updateCount();
System.out.println("事務處置以後");
}
}
3、TestCount.java
package net.battier.test;
import net.battier.dao.impl.CountImpl;
import net.battier.dao.impl.CountProxy;
/**
*測試Count類
*
* @author Administrator
*
*/
public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
不雅察代碼可以發明每個署理類只能為一個接口辦事,如許一來法式開辟中必定會發生過量的署理,並且,一切的署理操作除挪用的辦法紛歧樣以外,其他的操作都一樣,則此時確定是反復代碼。處理這一成績最好的做法是可以經由過程一個署理類完玉成部的署理功效,那末此時就必需應用靜態署理完成。
再來看一下靜態署理:
JDK靜態署理中包括一個類和一個接口:
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
參數解釋:
Object proxy:指被署理的對象。
Method method:要挪用的辦法
Object[] args:辦法挪用時所須要的參數
可以將InvocationHandler接口的子類想象成一個署理的終究操作類,調換失落ProxySubject。
Proxy類:
Proxy類是專門完成署理的操作類,可以經由過程此類為一個或多個接口靜態地生成完成類,此類供給了以下的操作辦法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
參數解釋:
ClassLoader loader:類加載器
Class<?>[] interfaces:獲得全體的接口
InvocationHandler h:獲得InvocationHandler接口的子類實例
Ps:類加載器
在Proxy類中的newProxyInstance()辦法中須要一個ClassLoader類的實例,ClassLoader現實上對應的是類加載器,在Java中重要有一下三品種加載器;
Booststrap ClassLoader:此加載器采取C++編寫,普通開辟中是看不到的;
Extendsion ClassLoader:用來停止擴大類的加載,普通對應的是jre\lib\ext目次中的類;
AppClassLoader:(默許)加載classpath指定的類,是最常應用的是一種加載器。
靜態署理
與靜態署理類對比的是靜態署理類,靜態署理類的字節碼在法式運轉時由Java反射機制靜態生成,無需法式員手工編寫它的源代碼。靜態署理類不只簡化了編程任務,並且進步了軟件體系的可擴大性,由於Java 反射機制可以生成隨意率性類型的靜態署理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口供給了生成靜態署理類的才能。
靜態署理示例:
1、BookFacade.java
package net.battier.dao;
public interface BookFacade {
public void addBook();
}
2、BookFacadeImpl.java
package net.battier.dao.impl;
import net.battier.dao.BookFacade;
public class BookFacadeImpl implements BookFacade {
@Override
public void addBook() {
System.out.println("增長圖書辦法。。。");
}
}
BookFacadeProxy.java
package net.battier.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK靜態署理署理類
*
* @author student
*
*/
public class BookFacadeProxy implements InvocationHandler {
private Object target;
/**
* 綁定拜托對象並前往一個署理類
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//獲得署理對象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //要綁定接口(這是一個缺點,cglib填補了這一缺點)
}
@Override
/**
* 挪用辦法
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
System.out.println("事物開端");
//履行辦法
result=method.invoke(target, args);
System.out.println("事物停止");
return result;
}
}
3、TestProxy.java
package net.battier.test;
import net.battier.dao.BookFacade;
import net.battier.dao.impl.BookFacadeImpl;
import net.battier.proxy.BookFacadeProxy;
public class TestProxy {
public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
}
然則,JDK的靜態署理依附接話柄現,假如有些類並沒有完成接口,則不克不及應用JDK署理,這就要應用cglib靜態署理了。
Cglib靜態署理
JDK的靜態署理機制只能署理完成了接口的類,而不克不及完成接口的類就不克不及完成JDK的靜態署理,cglib是針對類來完成署理的,他的道理是對指定的目的類生成一個子類,並籠罩個中辦法完成加強,但由於采取的是繼續,所以不克不及對final潤飾的類停止署理。
示例
1、BookFacadeCglib.java
package net.battier.dao;
public interface BookFacade {
public void addBook();
}
2、BookCadeImpl1.java
package net.battier.dao.impl;
/**
* 這個是沒有完成接口的完成類
*
* @author student
*
*/
public class BookFacadeImpl1 {
public void addBook() {
System.out.println("增長圖書的通俗辦法...");
}
}
3、BookFacadeProxy.java
package net.battier.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 應用cglib靜態署理
*
* @author student
*
*/
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
* 創立署理對象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回調辦法
enhancer.setCallback(this);
// 創立署理對象
return enhancer.create();
}
@Override
// 回調辦法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物開端");
proxy.invokeSuper(obj, args);
System.out.println("事物停止");
return null;
}
}
4、TestCglib.java
package net.battier.test;
import net.battier.dao.impl.BookFacadeImpl1;
import net.battier.proxy.BookFacadeCglib;
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}