学的有点懵,有些理解还有些问题想问老师

学的有点懵,有些理解还有些问题想问老师

在Bean的声明周期的第五步和第八步方法中,因为所有bean在初始化的前后都会
   调用这个接口的对应的方法,所以它们的参数1为当前初始化的Bean对象,也就是
    我们在xml配置的UserDaoImpl这个类对象。
	参数2是配置类对象中的id的值,是这样嘛?
    <bean id="userDao" class="com.zhou.ioc.demo3.UserDaoImpl"/>
Proxy.newProxyInstance():对某个类产生代理类,返回Object类型的代理类对象实例
Proxy.newProxyInstance()需要三个参数:
参数1:需要代理的类的加载器
 参数2:动态代理类需要实现的接口,也就是配置文件<bean>标签id为userDao对应的实现类UserDaoImpl
            它所需要实现接口:UserDao
	    <bean id="userDao" class="com.zhou.ioc.demo3.UserDaoImpl"/>
参数3:表示帮组动态代理的方法 InvocationHandler(),这里我们使用内部类的方式去创建这个方法。
我们在这个内部类里面重写了InvocationHandler()方法的invoke。该invoke方法中需要三个参数: 
参数一:proxy是InvocationHandler中的invoke方法的参数名(从同学提问老师回答中看到的)
	     疑问:这proxy本身不就是在inovke方法中的参数嘛?我也知道这是invoke方法中的三个参数中
	               的其中一个Object类型的参数名,那他具体表示什么?
参数二:这里的method属性传入的是Method类的对象,这个method对象是用真正的方法名,由方法名
             和形参抽象出Method对象。(从同学提问老师回答中看到的)
	      疑问:因为前面进行了userDao.equlse的判断,我们可以得到在xml中配置id为userDao的这个类,
	      但是这个类中有这么多方法,这个Method表示的是哪个方法抽象出来的Method对象?而且这里
	      老师是不是说错了,它说的是这里的method属性传入的是Method类的对象,这里不应该是
	      “method属性传入的是Method方法的对象”嘛?  
参数三:args[]中传入的是原方法执行所需要的参数,由于参数可能有多个,所以使用数组(从同学提问老师
          回答中看到的)
	  疑问:这里我有点懵,原方法指的是哪个方法?id为userDao对应的类中有那么多方法。而且这里
	            又没进行筛选条件判断,这里指的是哪个方法?
	            
在该方法中,我们针对性的对某个方法进行增强,最后返回  return method.invoke(bean,args);
这里我也不太理解,method是哪个方法对象?inovke方法是什么方法?代理方法嘛?它所需要的这两个
参数是什么? 
执行完这句话之后返回一个Oject类型的值,然后赋值给Oject proxy,也就是最终返回打代理对象。



正在回答

登陆购买课程后可参与讨论,去登陆

4回答

同学你好,1、代理类是对对应的类产生的实例对象的代理,例如:

http://img1.sycdn.imooc.com//climg/5e773f8d09dcee5410660343.jpg

    2、如下所示,对条件成立的内容执行代理。

http://img1.sycdn.imooc.com//climg/5e7740650952c3c611730353.jpg

在invoke方法中执行对应方法的增强。

如果我的回答解决了你的疑惑,请采纳,祝学习愉快~

  • jia_蛙 提问者 #1
    麻烦老师看一下
    2020-03-22 18:58:06
提问者 jia_蛙 2020-03-22 18:55:22
老师,我刚刚看了一下动态代理,你看一下我结合这个案例的理解有没有错:
Proxy类是个调度器,它提供用于创建动态代理的静态方法类和实例,
由这些方法创建的动态代理类,它也是所有类的超类.它有提供一个
newProxyInstance静态方法,这个返回指定接口的代理类的实例将方法
调用分派到指定的调用处理程序。用来创建动态代理的class和实例.

newProxyInstance这个创建代理类的方法需要三个参数:
参数1:类加载器
参数2:动态代理类需要实现的接口(案例中实现类是UserDaoImpl,它的接口是userDao,是
这样嘛?
参数3:
InvocationHandler接口是一个遵循单一职责原则的增强器,这个增强器
里面只有一个invoke接口方法我们就是在这个方法中进行业务增强的:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
我们在案例中是使用匿名内部类来实现它的。
这个invoke方法有三个参数:
参数1:代理对象  
参数2:我们要去优化,要去拦截的方法 
参数3:这个方法需要的参数
我们案例中就是在这里对save这个方法进行增强的,因为是动态代理,我们无法
用直接调用对象的方法来执行该方法,所以这里我们利用反射的原理来执行:
method.invoke(bean,args); 并且将该方法的返回值返回,如果不是该方法,就不
进行增强,直接执行该方法,然后返回。 
一般我们可以在这个反射方法执行前和执行后进行处理,达到增强的效果

Proxy.newProxyInstance的三个参数我们都有了,我们将 执行这个Proxy.newProxyInstance
这个静态方法,最后会根据我们配置文件中是否有id为userDao这个类对象进行Bean对象的返回,
如果有则返回代理后的bean对象,如果没有则返回原有bean对象

Proxy只管创建动态代理的实例,这个实例具体干什么事情是由这个
InvocationHandler来做的,它们的分工非常明确,一个只管生成员工,
一个负责定制员工工作执行的流程和标准。							
@Override
public Object postProcessAfterInitialization(final Object bean, String benName) throws BeansException {
    System.out.println("第八步:初始化后方法....");
    //判断是否对应的类,userDao为配置文件中类对象的id
    if("userDao".equals(benName)){
        //Proxy.newProxyInstance():对某个类产生代理类,返回Object类型的代理类对象
        Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //针对某个方法进行增强
                if("save".equals(method.getName())){
                     //调用方法前的增强,一般不会是输出,这里只是测试
                    System.out.println("权限校验====前置增强");
                    //通过反射执行我们需要代理的方法
                    Object obj = method.invoke(bean,args);
                    //调用方法后的增强
                    System.out.println("增强完毕====后置增强");
                    
                    return obj;
                }
                //如果是其他方法就直接执行该方法
                return method.invoke(bean,args);
            }
        });
        return proxy;
    }else {
        return  bean;
    }
}
这里我增强这里我稍微修改了一下,还有一个问题就是newProxyInstance的第二个参数表示:
动态代理类需要实现的接口(案例中实现类是UserDaoImpl,它的接口是userDao,是这样嘛?
麻烦老师看一下我的理解有没有问题


  • 同学你好,同学的理解没有问题,很棒,继续加油。 如果我的回答解决了你的疑惑,请采纳,祝学习愉快~
    2020-03-22 19:44:27
  • 提问者 jia_蛙 回复 好帮手慕小班 #2
    好的 谢谢老师!
    2020-03-22 20:50:00
提问者 jia_蛙 2020-03-22 16:09:23
疑问2:这里的代理类指的是InvocationHandler这个接口类的实例嘛?

疑问3:它是怎么知道来确定我们要将哪个方法抽象出来成method对象的呀?还是说它会将类里面的
全部方法都抽象成method对象,然后经过我们的if筛选来针对性的对这个类进行增强嘛?
								


好帮手慕小班 2020-03-22 15:07:43

同学你好,1、同学的说法是正确的。Object bean, String beanName是 applicationContext.getBean获取对应到对应的对象和对象名。

        2、疑问:proxy本身不就是在inovke方法中的参数嘛?我也知道这是invoke方法中的三个参数中的其中一个Object类型的参数名,那他具体表示什么.

    其实这里的proxy参数传递的即是代理类的实例。

        3、疑问:这个Method表示的是哪个方法抽象出来的Method对象。

这里的method就是需要调用的方法的代理对象,即需要执行的方法;所以这里传递的参数就是需要执行的方法。

http://img1.sycdn.imooc.com//climg/5e7709df09c168bb08750164.jpg

        4、原方法指的是哪个方法,原方法其实就是未代理前的方法。

        疑问:又没进行筛选条件判断,这里指的是哪个方法

http://img1.sycdn.imooc.com//climg/5e770dfa09102d4a08370232.jpg

如上所示,进行了条件筛选。所以还麻烦同学具体描述一下-->没进行筛选条件判断。

        5、method是哪个方法对象-->传递的就是需要调用的方法。

invoke方法:

        invoke()方法是Method类的一个方法,在执行save()、update()、delete()等方法时,会去调用invoke()方法,执行invoke()方法中的内容。

        这里的Method就是Method类型的参数,Method是java.lang.reflect下的一个类。

method.invoke的意思其实就是执行方法的意思。

如果老师没有理解正确同学想表达的意思,还麻烦同学具体描述一下。

如果我的回答解决了你的疑惑,请采纳,祝学习愉快~

  • 提问者 jia_蛙 #1
    麻烦老师看一下
    2020-03-22 16:09:37
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师