欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
  思路整理:
 
  1.涉及的角色:
 
  ①被代理类;
 
  ②被代理类要实现的接口;
 
  ③代理类;
 
  ④动态创建“代理类的对象”的类;
 
  ⑤注解类(注解在方法上);
 
  ⑥IOC容器:BeanFactory(自己实现IOC容器:https://www.cnblogs.com/laipimei/p/11205510.html)。
 
  2.实现步骤:
 
  (1)被代理类、被代理类的接口、InOutLog注解类的创建;
 
  (2)创建一个“动态代理类”,并把“被代理类的实例”传给该代理类;在该动态代理类的invoke()方法中,实现日志的输出,也是在该invoke()方法中调用、执行真正的代理类要执行的那个方法。
 
  (3)创建一个可以动态创建“代理类的实例”的类,通过该类的getProxyInstance(Objectobj)方法可以得到一个动态代理类的实例。
 
  (4)给方法加通知注解,该方法的实例须已交由IOC容器管理的;
 
  (5)遍历BeanFactory,找出方法上有@InOutLog注解的bean,为这些bean生成代理类对象(步骤:MyProxy3.getProxyInstance(Objectobj));
 
  (6)用代理类的实例去替代BeanFactory中的被代理类的实例;
 
  三、代码实现:
 
  被代理类的接口:
 
  packageMyIOCAndMyAop.bean;
 
  publicinterfaceSubject{
 
  voidtest();
 
  }
 
  被代理类:
 
  1packageMyIOCAndMyAop.bean;
 
  2
 
  3importMyIOCAndMyAop.Annotations.InOutLog;
 
  4importMyIOCAndMyAop.Annotations.MyAutowired;
 
  5importMyIOCAndMyAop.Annotations.MyComponent;
 
  6
 
  7/**
 
  8*被代理类
 
  9*/
 
  10@MyComponent
 
  11publicclassPersonimplementsSubject{
 
  12
 
  13@MyAutowired
 
  14privateStudentstudent;
 
  15
 
  16@InOutLog
 
  17publicvoidtest(){
 
  18System.out.println(this+".test():"+student);
 
  19}
 
  20}
 
  InOutLog注解类:
 
  packageMyIOCAndMyAop.Annotations;
 
  importjava.lang.annotation.ElementType;
 
  importjava.lang.annotation.Retention;
 
  importjava.lang.annotation.RetentionPolicy;
 
  importjava.lang.annotation.Target;
 
  @Target(ElementType.METHOD)
 
  @Retention(RetentionPolicy.RUNTIME)
 
  public@interfaceInOutLog{
 
  }
 
  动态代理类:
 
  publicclassMyInvocationHandler2implementsInvocationHandler{
 
  privateObjectobject;//被代理类
 
  privateObjectinvoke;
 
  publicvoidsetObject(Objectobject){
 
  this.object=object;
 
  }
 
  /**
 
  *在BeanFactory中,方法上有@InOutLog注解,则生成动态代理方法
 
  */
 
  @Override
 
  publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
 
  //这里做判断,看是否需要做下面的输出
 
  Booleanbool=false;
 
  //!!!注意,要用被代理类的对象去判断其method方法上是否有@InOutLog注解,而不是用入参method对象(该method对象是被代理类的接口的)
 
  //怎么处理入参的类型:见MyAOP2.这里没有做入参处理,可能会报方法找不到异常,注意!!!
 
  MethoddeclaredMethod=object.getClass().getDeclaredMethod(method.getName());
 
  if(null!=declaredMethod.getAnnotation(InOutLog.class)){
 
  System.out.println("我是日志输出~~~start~~~");
 
  bool=true;
 
  }
 
  invoke=method.invoke(object,args);
 
  //这里做判断,同上
 
  if(bool){
 
  System.out.println("我是日志输出~~~end~~~");
 
  System.out.println("------------------------------------------------------------------------------");
 
  }
 
  returninvoke;
 
  }
 
  }
 
  动态创建“代理类的对象”的类:
 
  publicclassMyProxy2{
 
  /**
 
  *动态的创建一个代理类的对象
 
  *MyProxy动态创建的“代理类的对象”:
 
  *classAimplementsSubject{
 
  *privateHandlerhandler;
 
  *publicvoidtest(){
 
  *//获得到当前方法名
 
  *handler.invoke();
 
  *}
 
  *}
 
  */
 
  publicstaticObjectgetProxyInstance(Objectobj){
 
  MyInvocationHandler2handler=newMyInvocationHandler2();
 
  handler.setObject(obj);
 
  returnProxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
 
  }
 
  /**
 
  *对于有@InOutLog注解的,用代理类的bean来替代BeanFactory中的被代理类的bean。
 
  *这一步很重要,因为当执行到bean.method(),执行的就一定是bean对应的method()方法,
 
  *如果此时没有用代理类对象去替换,那么执行的就是没有InOutLog的原来的那个方法。
 
  */
 
  publicstaticvoidupdateBean(StringcompleteClassName,Objectobject){
 
  MyIOC.updateBeanFromBeanFactory(completeClassName,getProxyInstance(object));//(全类名,代理类的bean)
 
  }
 
  }
 
  ①扫描BeanFactory,找出方法上有@InOutLog注解的bean,为其创建代理类对象,并替代原bean。②使用测试:
 
  publicclassMyAOP2{
 
  publicstaticvoidmain(String[]args){
 
  /**
 
  *使用步骤:
 
  *①給指定类的某个方法加@InOutLog注解;
 
  *②通过BeanFactory或的该类的实例;
 
  *③执行bean.method();
 
  *效果:method()方法的前后有了log的输出。
 
  */
 
  StringcompleteClassName="MyIOCAndMyAop.bean.Person";
 
  Objectbean=MyIOC.getBean(completeClassName);
 
  Subjectperson=(Subject)bean;
 
  person.test();
 
  }
 
  static{
 
  init();
 
  }
 
  publicstaticvoidinit(){
 
  updateBeanFromBeanFactory();
 
  }
 
  /**
 
  *扫描BeanFactory,找出方法上有@InOutLog注解的bean,为其创建代理类对象,并替代原bean。
 
  */
 
  publicstaticvoidupdateBeanFromBeanFactory(){
 
  for(Map.Entry<String,Object>entry:MyIOC.getBeanFactory().entrySet()){
 
  for(Methodmethod:entry.getValue().getClass().getDeclaredMethods()){
 
  if(null!=method.getAnnotation(InOutLog.class)){
 
  MyProxy2.updateBean(entry.getKey(),entry.getValue());
 
  }
 
  }
 
  }
 
  }
 
  }

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h56947.shtml