加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Java的动态代理机制及Spring的实现方式

发布时间:2020-12-13 21:18:58 所属栏目:PHP教程 来源:网络整理
导读:学习Java的同学注意了!!! 学习进程中遇到甚么问题或想获得学习资源的话,欢迎加入Java学习交换群,群号码: 183993990 我们1起学Java! JAVA 代理实现 代理的实现分动态代理和静态代理,静态代理的实现是对已生成了的JAVA类进行封装。 动态代理则是在运行

学习Java的同学注意了!!! 
学习进程中遇到甚么问题或想获得学习资源的话,欢迎加入Java学习交换群,群号码:183993990  我们1起学Java!


JAVA 代理实现

代理的实现分动态代理和静态代理,静态代理的实现是对已生成了的JAVA类进行封装。

动态代理则是在运行时生成了相干代理累,在JAVA中生成动态代理1般有两种方式。

JDK自带实现方法

JDK实现代理生成,是用类 java.lang.reflect.Proxy,实现方式以下

EX:

public class JDKProxy {

      public static Object getPoxyObject(final Object c) {

            return Proxy.newProxyInstance(c.getClass().getClassLoader(),c.getClass().getInterfaces(),// JDK实现动态代理,但JDK实现必须需要接口

                        new InvocationHandler() {

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

                                    // TODO Auto-generated method stub

                                    Object reObj = null;

                                    System.out.print("you say: ");

                                    reObj = method.invoke(c,args);

                                    System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"

                                                + Calendar.getInstance().get(Calendar.MINUTE) + " "

                                                + Calendar.getInstance().get(Calendar.SECOND) + "]");

                                    return reObj;

                              }

                        });

      }

}

测试代理类方法

public class TestForPoxy {

      public static void main(String[] args) {

            ServiceTest service = new ServiceTestImpl();

            System.out.println(service.getClass().getSimpleName());

            ServiceTest poxyService = (ServiceTest) JDKProxy.getPoxyObject(service);

            System.out.println(poxyService.getClass().getSuperclass());

            poxyService.saySomething("hello,My QQ code is 107966750.");

            poxyService.saySomething("what 's your name?");

            poxyService.saySomething("only for test,hehe.");

1, Proxy实现代理的目标类必须有实现接口

2, 生成出来的代理类为接口实现类,和目标类不能进行转换,只能转为接口实现类进行调用

明显特点:通过此方法生成出来的类名叫做 $Proxy0

用CGLIB包实现

CGLIB是1个开源项目,官方网址是:http://cglib.sourceforge.net/,可以去上面下载最新JAR包,

本项目用的是cglib⑶.0.jar

本项目还加入了依赖JAR包asm⑷.0.jar,asm-util⑷.0.jar

实现方式以下

EX:

public class CGLIBProxy {

      public static Object getPoxyObject(Object c) {

            Enhancer enhancer = new Enhancer();

            enhancer.setSuperclass(c.getClass());

            enhancer.setCallback(new MethodInterceptor() {

                  public Object intercept(Object arg0,Method arg1,Object[] arg2,MethodProxy proxy) throws Throwable {

                        System.out.print("you say: ");

                        proxy.invokeSuper(arg0,arg2);

                        System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"

                                    + Calendar.getInstance().get(Calendar.MINUTE) + " " + Calendar.getInstance().get(Calendar.SECOND)

                                    + "]");

                        return null;

                  }

            });

            return enhancer.create();

//          ServiceTest poxyService = (ServiceTest) JDKProxy.getPoxyObject(service);

            ServiceTest poxyService = (ServiceTest) CGLIBProxy.getPoxyObject(service);

 

1, CGLIB实现方式是对代理的目标类进行继承

2, 生成出了的代理类可以没方法,生成出来的类可以直接转换成目标类或目标类实现接口的实现类,因JAVA向上转换

明显特点:通过输出看出,看诞生成出的代理类的parent类为代理的目标类

 

Spring  AOP的代理类机制分析

在spring中,bean都是由动态代理生成出来的,那末究竟是用JDK的Proxy类实现呢,还是用CGLIB方式实现呢。

AOP  Spring需要的依赖JAR包有:

spring-asm⑶.2.0.M1.jar

spring-beans⑶.2.0.M1.jar

spring-context⑶.2.0.M1.jar

spring-core⑶.2.0.M1.jar

spring-expression⑶.2.0.M1.jar

spring-aop⑶.2.0.M1.jar

spring-aspects⑶.2.0.M1.jar

commonscommons-logging⑴.1.1commons-logging⑴.1.1.jar

aopallianceaopalliance.jar

libaspectjweaver.jar

 

实现AOP

先简单的实现AOP

配置以下

<?xml version="1.0" encoding="utf⑻"?>

<beans xmlns="http://www.springframework.org/schema/beans"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"

      xsi:schemaLocation="

      http://www.springframework.org/schema/beans

      http://www.springframework.org/schema/beans/spring-beans⑶.2.xsd

      http://www.springframework.org/schema/aop 

    http://www.springframework.org/schema/aop/spring-aop⑶.2.xsd">

      <bean id="test" class="org.ben.spring.service.Test" />

      <bean id="aspectBean" class="org.ben.spring.TestAspect" />

      <!-- 对Test类进行AOP拦截 -->

      <aop:config>

            <aop:aspect id="TestAspect" ref="aspectBean">

                  <!--配置切面-->

                  <aop:pointcut id="businessService"

                        expression="execution(* org.ben.spring.service.Test.say(..))" />

                  <aop:before pointcut-ref="businessService" method="doBefore" />

                  <aop:after pointcut-ref="businessService" method="doAfter" />

            </aop:aspect>

      </aop:config>

</beans>

然落后行运行结果以下,表示AOP拦截成功

AOP测试类

public class TestBeans {

            ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");

            Test test=(Test) ctx.getBean("test");

            System.out.println(test.getClass().getSimpleName());

            test.say();

输出:

do something in befor

welcome for test

do something in after

打印代理类的生成方式

第1种情况,Test不实现任何接口,代码以下

public class Test {

      public void say() {

            System.out.println("welcome for test,My QQ is 107966750");

在TestBeans中加入打印当前对象的名称

以下:

ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");

Test test=(Test) ctx.getBean("test");

System.out.println(test.getClass().getSimpleName());

test.say();

Test$$EnhancerByCGLIB$$4791b36c

super class is class org.ben.spring.service.Test

do something in after

明显看到用了AOP以后,输出的是代理类对象Test$$EnhancerByCGLIB$$bb9b6a7c.而且它的父类是我们的代理目标类。说明是有CGLIB生成的

第2种情况

 

XML的配置不变,改变代理目标类Test的实现方法,以下

public class Test implements TestInter{

和原来不同的是多继承了1个接口,接口中定义了say()方法

TestInter test=(TestInter) ctx.getBean("test");

System.out.println("super class is "+test.getClass().getSuperclass());

$Proxy0

super class is class java.lang.reflect.Proxy

welcome for test,My QQ is 107966750

结论

Spring AOP中,当拦截对象实现了接口时,生成方式是用JDK的Proxy类。当没有实现任何接口时用的是GCLIB开源项陌生成的拦截类的子类.

 附上本文测试的源码内容  源码下载

学习Java的同学注意了!!! 
学习进程中遇到甚么问题或想获得学习资源的话,欢迎加入Java学习交换群,群号码:183993990  我们1起学Java!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读