您好,登錄后才能下訂單哦!
簡(jiǎn)介
Java編程的目標(biāo)是實(shí)現(xiàn)現(xiàn)實(shí)不能完成的,優(yōu)化現(xiàn)實(shí)能夠完成的,是一種虛擬技術(shù)。生活中的方方面面都可以虛擬到代碼中。代理模式所講的就是現(xiàn)實(shí)生活中的這么一個(gè)概念:中介。
代理模式的定義:給某一個(gè)對(duì)象提供一個(gè)代理,并由代理對(duì)象控制對(duì)原對(duì)象的引用。
代理模式包含如下角色:
ISubject:抽象主題角色,是一個(gè)接口。該接口是對(duì)象和它的代理共用的接口。
RealSubject:真實(shí)主題角色,是實(shí)現(xiàn)抽象主題接口的類。
Proxy:代理角色,內(nèi)部含有對(duì)真實(shí)對(duì)象RealSubject的引用,從而可以操作真實(shí)對(duì)象。代理對(duì)象提供與真實(shí)對(duì)象相同的接口,以便在任何時(shí)刻都能代替真實(shí)對(duì)象。同時(shí),代理對(duì)象可以在執(zhí)行真實(shí)對(duì)象操作時(shí),附加其他的操作,相當(dāng)于對(duì)真實(shí)對(duì)象進(jìn)行封裝。
實(shí)現(xiàn)動(dòng)態(tài)代理的關(guān)鍵技術(shù)是反射。
靜態(tài)代理
代理模式有幾種,虛擬代理,計(jì)數(shù)代理,遠(yuǎn)程代理,動(dòng)態(tài)代理。主要分為兩類,靜態(tài)代理和動(dòng)態(tài)代理。靜態(tài)代理比較簡(jiǎn)單,是由程序員編寫(xiě)的代理類,并在程序運(yùn)行前就編譯好的,而不是由程序動(dòng)態(tài)產(chǎn)生代理類,這就是所謂的靜態(tài)。
考慮這樣的場(chǎng)景,管理員在網(wǎng)站上執(zhí)行操作,在生成操作結(jié)果的同時(shí)需要記錄操作日志,這是很常見(jiàn)的。此時(shí)就可以使用代理模式,代理模式可以通過(guò)聚合和繼承兩種方式實(shí)現(xiàn):
/**方式一:聚合式靜態(tài)代理 * @author Goser (mailto:goskalrie@163.com) * @Since 2016年9月7日 */ //1.抽象主題接口 public interface Manager { void doSomething(); } //2.真實(shí)主題類 public class Admin implements Manager { public void doSomething() { System.out.println("Admin do something."); } } //3.以聚合方式實(shí)現(xiàn)的代理主題 public class AdminPoly implements Manager{ private Admin admin; public AdminPoly(Admin admin) { super(); this.admin = admin; } public void doSomething() { System.out.println("Log:admin操作開(kāi)始"); admin.doSomething(); System.out.println("Log:admin操作結(jié)束"); } } //4.測(cè)試代碼 Admin admin = new Admin(); Manager m = new AdminPoly(admin); m.doSomething(); //方式二:繼承式靜態(tài)代理 //與上面的方式僅代理類和測(cè)試代碼不同 //1.代理類 public class AdminProxy extends Admin { @Override public void doSomething() { System.out.println("Log:admin操作開(kāi)始"); super.doSomething(); System.out.println("Log:admin操作開(kāi)始"); } } //2.測(cè)試代碼 AdminProxy proxy = new AdminProxy(); proxy.doSomething();
聚合實(shí)現(xiàn)方式中代理類聚合了被代理類,且代理類及被代理類都實(shí)現(xiàn)了同一個(gè)接口,可實(shí)現(xiàn)靈活多變。繼承式的實(shí)現(xiàn)方式則不夠靈活。
比如,在管理員操作的同時(shí)需要進(jìn)行權(quán)限的處理,操作內(nèi)容的日志記錄,操作后數(shù)據(jù)的變化三個(gè)功能。三個(gè)功能的排列組合有6種,也就是說(shuō)使用繼承要編寫(xiě)6個(gè)繼承了Admin的代理類,而使用聚合,僅需要針對(duì)權(quán)限的處理、日志記錄和數(shù)據(jù)變化三個(gè)功能編寫(xiě)代理類,在業(yè)務(wù)邏輯中根據(jù)具體需求改變代碼順序即可。
動(dòng)態(tài)代理
一般來(lái)說(shuō),對(duì)代理模式而言,一個(gè)主題類與一個(gè)代理類一一對(duì)應(yīng),這也是靜態(tài)代理模式的特點(diǎn)。
但是,也存在這樣的情況,有n各主題類,但是代理類中的“前處理、后處理”都是一樣的,僅調(diào)用主題不同。也就是說(shuō),多個(gè)主題類對(duì)應(yīng)一個(gè)代理類,共享“前處理,后處理”功能,動(dòng)態(tài)調(diào)用所需主題,大大減小了程序規(guī)模,這就是動(dòng)態(tài)代理模式的特點(diǎn)。
JDK動(dòng)態(tài)代理
實(shí)現(xiàn)
//1. 抽象主題 public interface Moveable { void move() throws Exception; } //2. 真實(shí)主題 public class Car implements Moveable { public void move() throws Exception { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽車行駛中…"); } } //3.事務(wù)處理器 public class TimeHandler implements InvocationHandler { private Object target; public TimeHandler(Object target) { super(); this.target = target; } /** * 參數(shù): *proxy 被代理的對(duì)象 *method 被代理對(duì)象的方法 *args 方法的參數(shù) * 返回: *Object 方法返回值 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); System.out.println("汽車開(kāi)始行駛…"); method.invoke(target, args); long stopTime = System.currentTimeMillis(); System.out.println("汽車結(jié)束行駛…汽車行駛時(shí)間:" + (stopTime - startTime) + "毫秒!"); return null; } } //測(cè)試類 public class Test { public static void main(String[] args) throws Exception{ Car car = new Car(); InvocationHandler h = new TimeHandler(car); Class<!--?--> cls = car.getClass(); /** *loader 類加載器 *interfaces 實(shí)現(xiàn)接口 *h InvocationHandler */ Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), h); m.move(); } }
代碼講解:
在測(cè)試代碼中,Proxy.newProxyInstance()方法需要3個(gè)參數(shù):類加載器(要進(jìn)行代理的類)、被代理類實(shí)現(xiàn)的接口,事務(wù)處理器。所以先實(shí)例化Car,實(shí)例化InvocationHandler的子類TimeHandler,將各參數(shù)傳入Proxy的靜態(tài)方法newProxyInstance()即可獲得Car的代理類,前面的靜態(tài)代理,代理類是我們編寫(xiě)好的,而動(dòng)態(tài)代理則不需要我們?nèi)ゾ帉?xiě)代理類,是在程序中動(dòng)態(tài)生成的。
JDK動(dòng)態(tài)代理步驟
1.創(chuàng)建一個(gè)實(shí)現(xiàn)InvocationHandler接口的類,它必須實(shí)現(xiàn)invoke()方法
2.創(chuàng)建被代理的類及接口
3.調(diào)用Proxy的靜態(tài)方法,創(chuàng)建一個(gè)代理類
4.通過(guò)代理調(diào)用方法
而為什么要進(jìn)行如此操作,可以從Proxy和InvocationHandler的源碼中找打答案。對(duì)源碼不感興趣的可以將下面的源碼部分小節(jié)略過(guò)。
JDK動(dòng)態(tài)代理原理與源碼
newProxyInstance()方法的源碼:
public static Object newProxyInstance(ClassLoader loader, Class<!--?-->[] interfaces, InvocationHandler h) throws IllegalArgumentException{ if (h == null) { throw new NullPointerException(); } final Class<!--?-->[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /*查找或生成指定的代理類*/ Class<!--?--> cl = getProxyClass0(loader, intfs); /*用指定的調(diào)用處理程序調(diào)用它的構(gòu)造函數(shù).*/ try { //獲得類的構(gòu)造函數(shù) final Constructor<!--?--> cons =cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { //當(dāng)需要代理的類實(shí)現(xiàn)了一個(gè)非public的接口時(shí),因?yàn)檫@樣的接口需要特殊的權(quán)限,因此調(diào)用doPrivilege(native 修飾的方法)創(chuàng)建代理實(shí)例。 return AccessController.doPrivileged(newPrivilegedAction<object>() { public Object run() { return newInstance(cons,ih); } }); } else { return newInstance(cons,ih); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } }
可以看到,獲得代理類的代碼是
Classcl = getProxyClass0(loader,intfs);
并由此獲得代理類的構(gòu)造函數(shù),生成代理類的實(shí)例返回給該方法的調(diào)用者。
繼續(xù)跟進(jìn)getProxyClass0()方法:
/** 生成代理類。調(diào)用該方法前必須使用checkproxyaccess方法執(zhí)行權(quán)限檢查。*/ private static Class<!--?--> getProxyClass0(ClassLoader loader, Class<!--?-->... interfaces) { //檢查實(shí)現(xiàn)的接口數(shù),65535這個(gè)數(shù)字好特殊,端口數(shù)好像也是這個(gè),這個(gè)數(shù)字是由虛擬機(jī)所決定的,2^16-1個(gè) if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // 如果代理類已經(jīng)通過(guò)實(shí)現(xiàn)給定接口的類加載器創(chuàng)建了,則返回緩存中的該類的副本;否則將通過(guò)ProxyClassFactory創(chuàng)建代理類 return proxyClassCache.get(loader, interfaces); }
還是沒(méi)有看到代理類是怎么生成的,只知道代理類是從proxyClassCache中取得的,這個(gè)變量是與緩存相關(guān)的一個(gè)對(duì)象,查看該變量的聲明與初始化:
private static final WeakCache<classloader,>[], Class<!--?-->> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());</classloader,>
可以發(fā)現(xiàn)proxyClassCache是個(gè)用來(lái)緩存代理類的類變量,大家知道類變量的特點(diǎn)是與類一一對(duì)應(yīng),在一個(gè)虛擬機(jī)中類只有一個(gè),對(duì)應(yīng)著在一個(gè)虛擬機(jī)中類變量也只有一個(gè),且在此處,在Proxy類被加載的時(shí)候就賦值了。在賦值操作的參數(shù)中有ProxyClassFactory()這么一個(gè)構(gòu)造函數(shù),這個(gè)是動(dòng)態(tài)代理中的關(guān)鍵:生成代理類的類文件字節(jié)碼。繼續(xù)跟進(jìn)去,找到代理類的生成之處了:
/** 根據(jù)給定的類加載器和接口數(shù)組生成代理類的工廠類*/ private static final class ProxyClassFactory implements BiFunction<classloader,class<?>[], Class<!--?-->> { // 所有代理類名稱的前綴 private static final String proxyClassNamePrefix = "$Proxy"; //用于生成唯一代理類名稱的下一個(gè)序號(hào) private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class<!--?--> apply(ClassLoader loader,Class<!--?-->[] interfaces) { Map<class<?>, Boolean>interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<!--?--> intf : interfaces) { /* 驗(yàn)證類加載器將此接口的名稱解析為實(shí)際對(duì)象的名稱。*/ Class<!--?--> interfaceClass =null; try { interfaceClass = Class.forName(intf.getName(),false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from classloader"); } /* 驗(yàn)證類對(duì)象確實(shí)是一個(gè)接口。*/ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /*確保接口唯一*/ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null; // 代理類的包名 /*記錄非公開(kāi)代理接口的包,以便將代理類定義在同一個(gè)包中。確認(rèn)所有非公共代理接口都在同一個(gè)包中。*/ for (Class<!--?--> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { String name =intf.getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException( "non-public interfaces fromdifferent packages"); } } } if (proxyPkg == null) { // 如果沒(méi)有非公開(kāi)的代理接口,使用com.sun.proxy作為包名 proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } /* 生成代理類名的序號(hào)*/ long num = nextUniqueNumber.getAndIncrement(); //生成全類名 String proxyName = proxyPkg + proxyClassNamePrefix + num; /*生成代理類字節(jié)碼 */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName,interfaces); try { return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString()); } } }
在ProxyClassFactory中,可以看到產(chǎn)生代理類的具體邏輯,大致上是,根據(jù)傳遞的被代理類及其實(shí)現(xiàn)的接口生成代理類的字節(jié)碼加載到緩存中,但是加載到緩存中只是一個(gè).java文件也不能用,所以底層還有編譯等操作。到這里,可以大致的看清JDK中動(dòng)態(tài)代理的面孔了,實(shí)現(xiàn)的步驟為:
1.創(chuàng)建代理類的源碼;
2.對(duì)源碼進(jìn)行編譯成字節(jié)碼;
3.將字節(jié)碼加載到內(nèi)存;
4.實(shí)例化代理類對(duì)象并返回給調(diào)用者;
底層的代碼我們看不到,但是我們可以查看其生成的字節(jié)碼:
//獲得字節(jié)碼的測(cè)試方法 byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy1", Car.class.getInterfaces()); FileOutputStream out = null; try { out = new FileOutputStream(System.getProperty("user.dir") + "\\$Proxy1.class"); out.write(classFile); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } //生成的字節(jié)碼: importcn.com.goser.proxy.imooc.staticproxy.Moveable; importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Method; importjava.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy1 extends Proxy implements Moveable { private static Method m1; private static Method m3; private static Method m0; private static Method m2; public $Proxy1(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } public final boolean equals(Object paramObject) throws { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final void move() throws Exception { try { this.h.invoke(this, m3, null); return; } catch (Exception localException) { throw localException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final int hashCode() throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final String toString() throws { try { return (String)this.h.invoke(this, m2, null); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("cn.com.goser.proxy.imooc.staticproxy.Moveable").getMethod("move", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch (NoSuchMethodExceptionlocalNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundExceptionlocalClassNotFoundException) { } throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } }
生成的字節(jié)碼比較長(zhǎng),但是在字節(jié)碼中最關(guān)鍵的信息是代理類的聲明:
public final class $Proxy1 extends Proxy
可以看到生成的代理類是繼承了Proxy類的,這就是說(shuō)明了為什么使用JDK動(dòng)態(tài)代理不能實(shí)現(xiàn)繼承式動(dòng)態(tài)代理,原因是Java不允許多繼承,而生成的代理類本身就已經(jīng)繼承了Proxy類。
至此,JDK的動(dòng)態(tài)代理的使用及底層原理分析完畢,揭下動(dòng)態(tài)代理的神秘面紗,果然是枚美女。
至于最底層的native方法是怎么動(dòng)態(tài)生成代理類的字節(jié)碼我們也可以簡(jiǎn)單的模擬一下,先分析下模擬的步驟:首先要生成一段代理類的源碼,然后將源碼編譯后生成代理類的實(shí)例返回給調(diào)用者。依據(jù)此步驟開(kāi)始編寫(xiě)我們的模擬代碼:
/** * JDK java.lang.reflect.Proxy的模擬 * @author Goser (mailto:goskalrie@163.com) * @Since 2016年9月7日 */ public class Proxy { private static final String RT = "\r\n"; public static Object newProxyInstance() throws Exception{ //聲明一段源碼 String sourceCode = "packagecn.com.goser.proxy.jdk.simulate;"+ RT + "importcn.com.goser.proxy.imooc.staticproxy.Admin;" + RT + "importcn.com.goser.proxy.imooc.staticproxy.Manager;" + RT + "http://以聚合方式實(shí)現(xiàn)的代理主題" + RT + "public class $Proxy0 implementsManager{" + RT + " privateAdmin admin;" + RT + " public$Proxy0(Admin admin) {" + RT + " super();" + RT + " this.admin= admin;" + RT + " }" + RT + " publicvoid doSomething() {" + RT + " System.out.println(\"Log:admin操作開(kāi)始\");" + RT + " admin.doSomething();" + RT + " System.out.println(\"Log:admin操作結(jié)束\");" + RT + " }" + RT + "}"; String filename = System.getProperty("user.dir") + "/src/main/java/cn/com/goser/proxy/jdk/simulate/$Proxy0.java"; File file = new File(filename); //使用org.apache.commons.io.FileUtils.writeStringToFile()將源碼寫(xiě)入磁盤(pán) //編寫(xiě)到處,可以運(yùn)行一下程序,可以在當(dāng)前目錄中看到生成的.java文件 FileUtils.writeStringToFile(file,sourceCode); //獲得當(dāng)前系統(tǒng)中的編譯器 JavaCompiler complier = ToolProvider.getSystemJavaCompiler(); //獲得文件管理者 StandardJavaFileManager fileMgr =complier.getStandardFileManager(null, null, null); Iterable its =fileMgr.getJavaFileObjects(filename); //編譯任務(wù) CompilationTask task = complier.getTask(null, fileMgr, null, null, null, its); //開(kāi)始編譯,執(zhí)行完可在當(dāng)前目錄下看到.class文件 task.call(); fileMgr.close(); //load到內(nèi)存 ClassLoader loader = ClassLoader.getSystemClassLoader(); Class cls = loader.loadClass("cn.com.goser.proxy.jdk.simulate.$Proxy0"); //生成代理類對(duì)象 Constructor ct = cls.getConstructor(Admin.class); return ct.newInstance(new Admin()); } } class test{ public static void main(String[] args) throws Exception { Manager m = (Manager)Proxy.newProxyInstance(); m.doSomething(); } }
運(yùn)行測(cè)試代碼,結(jié)果和手工編寫(xiě)的結(jié)果一致,完成了JDK中動(dòng)態(tài)代理的實(shí)現(xiàn)模擬。
cglib動(dòng)態(tài)代理
前面分析到,因?yàn)镴ava只允許單繼承,而JDK生成的代理類本身就繼承了Proxy類,因此,使用JDK實(shí)現(xiàn)的動(dòng)態(tài)代理不能完成繼承式的動(dòng)態(tài)代理,但是我們可以使用cglib來(lái)實(shí)現(xiàn)繼承式的動(dòng)態(tài)代理。
大名鼎鼎的Spring中就含有cglib動(dòng)態(tài)代理,在此也以Spring中自帶的cglib完成動(dòng)態(tài)代理的實(shí)現(xiàn):
//1.具體主題 public class Train{ public void move(){ System.out.println("火車行駛中…"); } } //2.生成代理 public class CGLibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class<!--?--> clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** * 攔截所有目標(biāo)類方法的調(diào)用 * 參數(shù): * obj目標(biāo)實(shí)例對(duì)象 *method 目標(biāo)方法的反射對(duì)象 * args方法的參數(shù) * proxy代理類的實(shí)例 */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { //代理類調(diào)用父類的方法 System.out.println("日志開(kāi)始"); proxy.invokeSuper(obj, args); System.out.println("日志結(jié)束"); return null; } } //3.測(cè)試 public class Test { public static void main(String[] args) { CGLibProxy proxy = new CGLibProxy(); Train t = (Train) proxy.getProxy(Train.class); t.move(); } }
小結(jié)
動(dòng)態(tài)代理與靜態(tài)代理相比較,最大的好處是接口中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個(gè)集中的方法中處理。在接口方法數(shù)量比較多的時(shí)候,我們可以進(jìn)行靈活處理,而不需要像靜態(tài)代理那樣對(duì)每一個(gè)方法或方法組合進(jìn)行處理。Proxy 很美很強(qiáng)大,但是僅支持 interface 代理。Java 的單繼承機(jī)制注定了這些動(dòng)態(tài)代理類們無(wú)法實(shí)現(xiàn)對(duì) class 的動(dòng)態(tài)代理。好在有cglib為Proxy提供了彌補(bǔ)。class與interface的區(qū)別本來(lái)就模糊,在java8中更是增加了一些新特性,使得interface越來(lái)越接近c(diǎn)lass,當(dāng)有一日,java突破了單繼承的限制,動(dòng)態(tài)代理將會(huì)更加強(qiáng)大。
以上就是本文關(guān)于Java設(shè)計(jì)模式之代理模式原理及實(shí)現(xiàn)代碼分享的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:快速理解Java設(shè)計(jì)模式中的組合模式、Java設(shè)計(jì)者模式簡(jiǎn)單工廠模式解析、Java設(shè)計(jì)模式之訪問(wèn)者模式使用場(chǎng)景及代碼示例等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。