温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java中怎么增强一个类的功能

发布时间:2021-07-01 14:50:21 来源:亿速云 阅读:110 作者:Leah 栏目:大数据

Java中怎么增强一个类的功能,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

首先第一种,直接在方法中写上要添加的功能,这种方式最不推荐,因为它违反了java代码“对扩展开放,对修改关闭”的原则,会影响之前代码的使用,而且后期维护也非常麻烦。

第二种,使用继承,提供一个类继承当前类,重写要增强的方法,可以实现对功能的添加或增强,继承的方式不影响原来类的使用,而且代码实现简单,但是只能增强一个类的功能,不能批量增强一类事物的功能。如果多个类想要同时修改功能,就要写很多子类,这样会造成代码冗余,而且不利于后期的维护。

第三种,使用装饰器模式,举例,这里有一个Singer类,实现了Sing接口,现在想要对Singer类的sing方法增强,代码如下:

  1. public interface SingAble {  

  2.     public void sing();  

  3. }  

  1. public class Singer implements SingAble {  

  2.     @Override  

  3.     public void sing() {  

  4.         System.out.println("the original sing!");  

  5.     }  

  6. }  

  1. public class Decorator implements SingAble {  

  2.     private SingAble singer;   

  3.     public Decorator(SingAble singer){  

  4.         this.singer = singer;  

  5.     }  

  6.     @Override  

  7.     public void sing() {  

  8.         System.out.println("before sing...");  

  9.         Singer.sing();  

  10.         System.out.println("after sing...");  

  11.     }  

  12. }  

  1. public class DecoratorTest {  

  2.     public static void main(String[] args) {  

  3.         SingAble singer = new Singer();  

  4.         SingAble obj = new Decorator(singer);  

  5.         obj.sing();  

  6.     }  

  7. }  

输出:

before sing...

sing a song...

after sing...

装饰器模式可以动态地为一类事物增强功能,而且可以动态的撤销,而继承的功能是静态的,并不能动态增删。

第五种,使用代理模式,代码如下:

  1. public interface SingAble{  

  2.     public void sing();  

  3. }  

  1. public class Singer implements SIngAble{  

  2.     @Override  

  3.     public void sing() {  

  4.         System.out.println("sing a song...");  

  5.     }  

  6. }  

  1. public class Proxy implements SingAble{  

  2.     private SingAble singer;  

  3.     public Proxy(){  

  4.         this.singer = new Singer();  

  5.     }  

  6.     @Override  

  7.     public void sing() {  

  8.         before();  

  9.         singer.sing();  

  10.         atfer();  

  11. }  

  12. private void before() {  

  13.         System.out.println("before sing...");  

  14.     } 

  15.     private void atfer() {  

  16.         System.out.println("after sing...");  

  17.     }  

  18. }  

  1. public class ProxyTest {  

  2.     public static void main(String[] args) {  

  3.         SingAble singer = new Proxy();  

  4.         singer.sing();  

  5.     }  

  6. }  

输出:

before sing...

sing a song...

after sing...

代理模式与装饰器模式看似很相像,实际上还是有区别的,装饰器模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,其偏重点在为装饰的对象增强功能,然而代理模式更偏向于控制对对象的访问。代理类就像一个中介,可以对它的客户隐藏一个对象的具体信息。使用代理模式的时候直接在代理类中创建一个对象的实例,因此代理类和真实对象之间的的关系在编译时就已经确定。而使用装饰器模式的时候,通常是将原始对象作为参数传入。

代理模式同样可以批量增加一类事物的功能,同时对功能的划分更为清晰,便于后期维护,这一点在动态代理中尤为明显。动态代理通过反射可以同时对多个方法做处理,而如果使用装饰者模式,方法较多时,装饰器类就会变得复杂。

动态代理分为jdk代理和cglib代理两种方式,其中jdk的动态代理是基于接口实现,被代理对象必须实现接口,而cglib是基于父类实现,更具有普适性,下面分别使用jdk与cglib 方式实现对SInger类的增强,代码如下:

jdk方式:

  1. public class Singer_proxy {

  2.     public static void main(String[] args) {

  3.         final Singer singer = new Singer();

  4.         Sing proxy = (Sing) Proxy.newProxyInstance(singer.getClass().getClassLoader(), singer.getClass().getInterfaces(), new InvocationHandler() {

  5.             @Override

  6.             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

  7.                 System.out.println("宣传。。。");//此处可抽取方法,做到业务之间隔离

  8.                 Object invoke = method.invoke(singer, args);

  9.                 System.out.println("收场。。。");//同上

  10.                 return invoke;

  11.             }

  12.         });

  13.         proxy.song();

  14.     }

  15. }

cglib方式:

  1. public class Singer_proxy {

  2.     public static void main(String[] args) {

  3.         final Singer singer = new Singer();

  4.         Enhancer enhancer = new Enhancer();

  5.         enhancer.setSuperclass(Singer.class);

  6.         enhancer.setCallback(new MethodInterceptor() {

  7.             @Override

  8.             public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

  9.                 System.out.println("宣传。。。");

  10.                 Object invoke = method.invoke(singer, objects);

  11.                 System.out.println("收场。。。");

  12.                 return invoke;

  13.             }

  14.         });

  15.         Singer proxy = (Singer) enhancer.create();

  16.         proxy.sing();

  17.     }

  18. }

Spring的AOP( Aspect Oriented Programming )面向切面编程,其底层就是使用动态代理来实现的,Spring内部集成了cglib,会根据对象是否实现接口来判断使用jdk方式还是cglib方式来实现对象的代理,当然也可以显式的设置为始终使用cglib方式代理。

AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度大大降低,同时提高程序的可重用性,提高了开发的效率,AOP形象地体现出了java代码“高内聚,低耦合”的思想。

Spring的AOP封装了动态代理,通过配置的方式,就可以实现在运行期间动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。通过配置“前置通知”、“后置通知”、“环绕通知”、“异常抛出通知”、“最终通知”五种“通知”类型(“通知”为面向切面编程中的术语,拦截到要增强的对象的方法时,要做的事情就称为“通知”),决定在具体什么位置添加对应功能,实际上环绕通知就可以实现其他所有通知的功能,代码如下所示,所以很多时候我们直接使用环绕通知。

  1. public Object around(ProceedingJoinPoint pjp) throws Throwable {

  2.         try {

  3.             System.out.println("前置通知。。。");

  4.             Object[] args = pjp.getArgs();

  5.             Object proceed = pjp.proceed(args);

  6.             System.out.println("后置通知。。。");

  7.             return proceed;

  8.         } catch (Exception e) {

  9.             e.printStackTrace();

  10.             System.out.println("异常抛出通知。。。");

  11.         }finally{

  12.             System.out.println("最终通知。。。");

  13.         }

  14.         return null;

  15. }

Spring的声明式事务管理,其底层也是通过AOP实现,使用的就是环绕通知,可以非常方便地对各种业务统一做事务管理。由于动态代理良好的解耦性,其实很多框架的都会使用到这项技术。

看完上述内容,你们掌握Java中怎么增强一个类的功能的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI