From b69409a9e456acf054f975202092b255c1a379cc Mon Sep 17 00:00:00 2001 From: maxy19 <315802767@qq.com> Date: Sat, 14 Dec 2019 12:47:19 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=E5=A2=9E=E5=8A=A0cglib=20=E5=9F=BA?= =?UTF-8?q?=E7=B1=BB=E6=B5=8B=E8=AF=95=E5=85=B6=E7=BB=93=E6=9E=9C=E3=80=82?= =?UTF-8?q?=E8=AF=81=E6=98=8E=E4=BB=A3=E7=90=86=E7=B1=BB=E7=94=9F=E6=88=90?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E4=BB=A5=E6=89=A7=E8=A1=8C=E8=BF=87=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 105 ++++++++++++++++++ pom.xml | 2 +- .../proxy/{IStudent.java => ISchool.java} | 2 +- src/main/com/mxy/design/proxy/SchoolImpl.java | 18 +++ .../com/mxy/design/proxy/SchoolProxy.java | 28 +++++ .../com/mxy/design/proxy/StudentImpl.java | 13 --- .../com/mxy/design/proxy/StudentProxy.java | 36 ------ .../proxy/dynamic/cglib/proxy/IStudent.java | 9 -- .../cglib/proxy/StudentCglibProxy.java | 23 +++- .../dynamic/cglib/proxy/StudentImpl.java | 13 --- .../dynamic/cglib/proxy/StudentService.java | 20 ++++ .../cglib/proxy/StudentServiceExtend.java | 20 ++++ .../proxy/StudentServiceExtendChildren.java | 18 +++ .../proxy/dynamic/jdk/proxy/IStudent.java | 9 -- ...udentJdkProxy.java => SchoolJdkProxy.java} | 8 +- .../proxy/dynamic/jdk/proxy/StudentImpl.java | 13 --- .../mxy/design/proxy/DynamicProxyTest.java | 49 ++++---- .../com/mxy/design/proxy/StaticProxyTest.java | 10 +- 18 files changed, 267 insertions(+), 129 deletions(-) create mode 100644 .gitignore rename src/main/com/mxy/design/proxy/{IStudent.java => ISchool.java} (72%) create mode 100644 src/main/com/mxy/design/proxy/SchoolImpl.java create mode 100644 src/main/com/mxy/design/proxy/SchoolProxy.java delete mode 100644 src/main/com/mxy/design/proxy/StudentImpl.java delete mode 100644 src/main/com/mxy/design/proxy/StudentProxy.java delete mode 100644 src/main/com/mxy/design/proxy/dynamic/cglib/proxy/IStudent.java delete mode 100644 src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentImpl.java create mode 100644 src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentService.java create mode 100644 src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtend.java create mode 100644 src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtendChildren.java delete mode 100644 src/main/com/mxy/design/proxy/dynamic/jdk/proxy/IStudent.java rename src/main/com/mxy/design/proxy/dynamic/jdk/proxy/{StudentJdkProxy.java => SchoolJdkProxy.java} (58%) delete mode 100644 src/main/com/mxy/design/proxy/dynamic/jdk/proxy/StudentImpl.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2e9e66e --- /dev/null +++ b/.gitignore @@ -0,0 +1,105 @@ +# Created by .ignore support plugin (hsz.mobi) +### Example user template template +### Example user template + +# IntelliJ project files +.idea +*.iml +out +gen +target +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + diff --git a/pom.xml b/pom.xml index 4a97004..504974e 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ cglib cglib - 3.2.10 + 3.3.0 diff --git a/src/main/com/mxy/design/proxy/IStudent.java b/src/main/com/mxy/design/proxy/ISchool.java similarity index 72% rename from src/main/com/mxy/design/proxy/IStudent.java rename to src/main/com/mxy/design/proxy/ISchool.java index 2477d73..93abe3f 100644 --- a/src/main/com/mxy/design/proxy/IStudent.java +++ b/src/main/com/mxy/design/proxy/ISchool.java @@ -1,6 +1,6 @@ package com.mxy.design.proxy; -public interface IStudent { +public interface ISchool { void save(); diff --git a/src/main/com/mxy/design/proxy/SchoolImpl.java b/src/main/com/mxy/design/proxy/SchoolImpl.java new file mode 100644 index 0000000..721c538 --- /dev/null +++ b/src/main/com/mxy/design/proxy/SchoolImpl.java @@ -0,0 +1,18 @@ +package com.mxy.design.proxy; + +public class SchoolImpl implements ISchool { + + public SchoolImpl(){ + //JDK动态代理通过反射会调用这个方法 + System.out.println(SchoolImpl.class+":JDK 动态代理反射调用。"); + } + @Override + public void save() { + System.out.println("保存学校信息ing"); + } + + @Override + public void delete() { + System.out.println("删除学校信息ing"); + } +} diff --git a/src/main/com/mxy/design/proxy/SchoolProxy.java b/src/main/com/mxy/design/proxy/SchoolProxy.java new file mode 100644 index 0000000..b5b1d21 --- /dev/null +++ b/src/main/com/mxy/design/proxy/SchoolProxy.java @@ -0,0 +1,28 @@ +package com.mxy.design.proxy; + +/** + * 重点类 静态代理 实现目标接口 + */ +public class SchoolProxy implements ISchool { + + private ISchool student; + + public SchoolProxy(ISchool iSchool) { + this.student = iSchool; + } + + @Override + public void save() { + System.out.println("==开启事务"); + student.save(); + System.out.println("==提交事务"); + } + + @Override + public void delete() { + //查询是否存在 + System.out.println("===开启事务"); + student.delete(); + System.out.println("===提交事务"); + } +} diff --git a/src/main/com/mxy/design/proxy/StudentImpl.java b/src/main/com/mxy/design/proxy/StudentImpl.java deleted file mode 100644 index 3193002..0000000 --- a/src/main/com/mxy/design/proxy/StudentImpl.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mxy.design.proxy; - -public class StudentImpl implements IStudent { - @Override - public void save() { - System.out.println("保存ing"); - } - - @Override - public void delete() { - System.out.println("删除ing"); - } -} diff --git a/src/main/com/mxy/design/proxy/StudentProxy.java b/src/main/com/mxy/design/proxy/StudentProxy.java deleted file mode 100644 index f5271c0..0000000 --- a/src/main/com/mxy/design/proxy/StudentProxy.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.mxy.design.proxy; - -import java.util.Random; - -/** - * 重点类 静态代理 实现目标接口 - */ -public class StudentProxy implements IStudent { - - private IStudent student; - - public StudentProxy(IStudent iStudent) { - this.student = iStudent; - } - - @Override - public void save() { - System.out.println("==开启事务"); - student.save(); - System.out.println("==提交事务"); - } - - @Override - public void delete() { - Random random = new Random(); - //查询是否存在 - if(random.nextBoolean()){ - System.out.println("===开启事务"); - student.delete(); - System.out.println("===提交事务"); - }else{ - System.out.println("===该用户已经被删除"); - } - - } -} diff --git a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/IStudent.java b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/IStudent.java deleted file mode 100644 index 6ff4a41..0000000 --- a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/IStudent.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.mxy.design.proxy.dynamic.cglib.proxy; - -public interface IStudent { - - void save(); - - void delete(); - -} diff --git a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentCglibProxy.java b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentCglibProxy.java index 77f85b6..51da3d0 100644 --- a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentCglibProxy.java +++ b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentCglibProxy.java @@ -7,17 +7,28 @@ import java.lang.reflect.Method; /** - * 动态代理 实现JDK 接口 + * 动态代理 实现GGLIB 接口 + * 注意: + * CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法, + * 并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final, + * 对于final类或方法,是无法继承的。 */ public class StudentCglibProxy implements MethodInterceptor { - + /** + * CGLib需要代理的目标对象 + */ + private Object target; @Override - public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { - return methodProxy.invokeSuper(o, objects); + public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + //可能造成死循环坑:而如果调用invokeSuper方法,则一定要使用被代理后的obj对象 + //return methodProxy.invokeSuper(obj, args); + //可能造成死循环坑:如果是用invoke方法一定要使用被代理的对象也就是上文中的target + return methodProxy.invoke(target, args); } - public T getInstance(Class objClass) { - return (T)Enhancer.create(objClass.getClass(), this); + public T getInstance(Object target) { + this.target = target; + return (T) Enhancer.create(target.getClass(), this); } } diff --git a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentImpl.java b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentImpl.java deleted file mode 100644 index dff60d9..0000000 --- a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentImpl.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mxy.design.proxy.dynamic.cglib.proxy; - -public class StudentImpl implements IStudent { - @Override - public void save() { - System.out.println("保存ing"); - } - - @Override - public void delete() { - System.out.println("删除ing"); - } -} diff --git a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentService.java b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentService.java new file mode 100644 index 0000000..2af2074 --- /dev/null +++ b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentService.java @@ -0,0 +1,20 @@ +package com.mxy.design.proxy.dynamic.cglib.proxy; + +public class StudentService { + + public StudentService() { + //CGLIB动态代理通过反射会调用这个方法 + System.out.println("基类==> CGLIB 动态代理反射调用。"); + } + public StudentService(String str) { + //避免混淆 + } + + public void save() { + System.out.println("保存ing"); + } + + public void delete() { + System.out.println("删除ing"); + } +} diff --git a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtend.java b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtend.java new file mode 100644 index 0000000..b4ea74c --- /dev/null +++ b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtend.java @@ -0,0 +1,20 @@ +package com.mxy.design.proxy.dynamic.cglib.proxy; + +public class StudentServiceExtend extends StudentService { + + public StudentServiceExtend() { + System.out.println("===>扩展类构造方法"); + } + + @Override + public void save(){ + System.out.println("===>扩展类Save"); + super.save(); + } + + @Override + public void delete(){ + System.out.println("===>扩展类delete"); + super.delete(); + } +} diff --git a/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtendChildren.java b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtendChildren.java new file mode 100644 index 0000000..36c86b8 --- /dev/null +++ b/src/main/com/mxy/design/proxy/dynamic/cglib/proxy/StudentServiceExtendChildren.java @@ -0,0 +1,18 @@ +package com.mxy.design.proxy.dynamic.cglib.proxy; + +public class StudentServiceExtendChildren extends StudentServiceExtend { + + public StudentServiceExtendChildren() { + System.out.println("===>扩展类子类构造方法"); + } + + @Override + public void save(){ + System.out.println("===>扩展类子类save"); + } + + @Override + public void delete(){ + System.out.println("===>扩展类子类delete"); + } +} diff --git a/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/IStudent.java b/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/IStudent.java deleted file mode 100644 index 02a7667..0000000 --- a/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/IStudent.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.mxy.design.proxy.dynamic.jdk.proxy; - -public interface IStudent { - - void save(); - - void delete(); - -} diff --git a/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/StudentJdkProxy.java b/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/SchoolJdkProxy.java similarity index 58% rename from src/main/com/mxy/design/proxy/dynamic/jdk/proxy/StudentJdkProxy.java rename to src/main/com/mxy/design/proxy/dynamic/jdk/proxy/SchoolJdkProxy.java index f2d6e96..183b0f5 100644 --- a/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/StudentJdkProxy.java +++ b/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/SchoolJdkProxy.java @@ -6,12 +6,16 @@ /** * 动态代理 实现JDK 接口 + * 重点:JDK动态代理只能对实现了接口的类生成代理,而不能针对类。 如果使用单纯的类,而这个类没有实现接口,会报错 + * 在spring里面 + * 1.当Bean实现接口时,Spring就会用JDK的动态代理。 + * 2.当Bean没有实现接口时,Spring使用CGlib是实现。 */ -public class StudentJdkProxy implements InvocationHandler { +public class SchoolJdkProxy implements InvocationHandler { private Object target; - public StudentJdkProxy(Object object) { + public SchoolJdkProxy(Object object) { this.target = object; } diff --git a/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/StudentImpl.java b/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/StudentImpl.java deleted file mode 100644 index 2c7cf4e..0000000 --- a/src/main/com/mxy/design/proxy/dynamic/jdk/proxy/StudentImpl.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mxy.design.proxy.dynamic.jdk.proxy; - -public class StudentImpl implements IStudent { - @Override - public void save() { - System.out.println("保存ing"); - } - - @Override - public void delete() { - System.out.println("删除ing"); - } -} diff --git a/src/test/com/mxy/design/proxy/DynamicProxyTest.java b/src/test/com/mxy/design/proxy/DynamicProxyTest.java index 5867323..1347c6b 100644 --- a/src/test/com/mxy/design/proxy/DynamicProxyTest.java +++ b/src/test/com/mxy/design/proxy/DynamicProxyTest.java @@ -1,7 +1,9 @@ package com.mxy.design.proxy; import com.mxy.design.proxy.dynamic.cglib.proxy.StudentCglibProxy; -import com.mxy.design.proxy.dynamic.jdk.proxy.StudentJdkProxy; +import com.mxy.design.proxy.dynamic.cglib.proxy.StudentService; +import com.mxy.design.proxy.dynamic.cglib.proxy.StudentServiceExtendChildren; +import com.mxy.design.proxy.dynamic.jdk.proxy.SchoolJdkProxy; import org.junit.Test; import java.util.Random; @@ -14,42 +16,31 @@ * 代理模式:代理类对被代理的对象有控制权,决定其执行或者不执行。 * 而装饰模式中,装饰类对代理对象没有控制权,只能为其增加一层装饰,以加强被装饰对象的功能。 * 动态代理:原理通过反射来获得代理的实现 常用的有JDK 自带jdkProxy 与 cglib 之前hibernate使用 javassist - * 好处:当时用动态代理 一个动态代理模板就能代理多个目标类 只需要传入接口 通过反射得到实现目标类方法 + * 好处:当使用动态代理 一个动态代理模板就能代理多个目标类 只需要传入接口 通过反射得到实现目标类方法 */ public class DynamicProxyTest { - @Test public void cglibProxyTest() { - System.out.println("====使用代理模式前"); - IStudent iStudent = new StudentImpl(); - iStudent.save(); - iStudent.delete(); - System.out.println(); - System.out.println("=====使用CGLIB代理模式后"); - IStudent cglibProxy = new StudentCglibProxy().getInstance(IStudent.class); + System.out.println("=====使用CGLIB代理模式"); + //去掉下面注释可以 会在指定位置生成文件 + //System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, ".\\\\classes"); + StudentService cglibProxy = new StudentCglibProxy().getInstance(new StudentServiceExtendChildren()); save(cglibProxy); delete(cglibProxy); } @Test public void jdkProxyTest() { - System.out.println("====使用代理模式前"); - IStudent iStudent = new StudentImpl(); - iStudent.save(); - iStudent.delete(); - System.out.println(); - System.out.println("=====使用JDK动态代理模式后"); - IStudent jdkProxy = new StudentJdkProxy(iStudent).getInstance(); - + System.out.println("=====使用JDK动态代理模式"); + ISchool jdkProxy = new SchoolJdkProxy(new SchoolImpl()).getInstance(); //与静态代理输出结果保持一致 save(jdkProxy); - //查询是否存在 delete(jdkProxy); } - private void delete(IStudent jdkProxy) { + private void delete(ISchool jdkProxy) { if (new Random().nextBoolean()) { System.out.println("===开启事务"); jdkProxy.delete(); @@ -59,10 +50,26 @@ private void delete(IStudent jdkProxy) { } } - private void save(IStudent jdkProxy) { + private void save(ISchool jdkProxy) { System.out.println("==开启事务"); jdkProxy.save(); System.out.println("==提交事务"); } + public void save(StudentService cglibProxy) { + System.out.println("==开启事务"); + cglibProxy.save(); + System.out.println("==提交事务"); + } + + public void delete(StudentService cglibProxy) { + if (new Random().nextBoolean()) { + System.out.println("===开启事务"); + cglibProxy.delete(); + System.out.println("===提交事务"); + } else { + System.out.println("===该用户已经被删除"); + } + } + } diff --git a/src/test/com/mxy/design/proxy/StaticProxyTest.java b/src/test/com/mxy/design/proxy/StaticProxyTest.java index 2d4fd1a..0816c19 100644 --- a/src/test/com/mxy/design/proxy/StaticProxyTest.java +++ b/src/test/com/mxy/design/proxy/StaticProxyTest.java @@ -22,12 +22,12 @@ public class StaticProxyTest { @Test public void logicTest() { System.out.println("====使用代理模式前"); - IStudent iStudent = new StudentImpl(); - iStudent.save(); - iStudent.delete(); + ISchool iSchool = new SchoolImpl(); + iSchool.save(); + iSchool.delete(); System.out.println(); - System.out.println("=====使用代理模式后"); - IStudent studentProxy = new StudentProxy(iStudent); + System.out.println("=====使用静态代理模式后"); + ISchool studentProxy = new SchoolProxy(iSchool); studentProxy.save(); studentProxy.delete(); }