func (d *Dispatcher) parseMiddleware(m *factory.MetaData) (middleware *injectableObject) {
	middleware = new(injectableObject)
	mwi := reflect.ValueOf(m.Instance)
	middleware.object = mwi.Interface()
	annotations := annotation.GetAnnotations(middleware.object)
	middleware.annotations = annotations
	mwType := mwi.Type()
	numOfMethod := mwi.NumMethod()
	for mi := 0; mi < numOfMethod; mi++ {
		methodHandler := new(injectableMethod)
		method := mwType.Method(mi)
		methodHandler.method = &method
		ma := d.parseAnnotation(mi, &method)
		methodHandler.annotations = ma
		mwh := annotation.FilterIn(ma, at.MiddlewareHandler{})
		if len(mwh) > 0 {
			methodHandler.hasMethodAnnotation = true
			hdl := newHandler(d.configurableFactory, middleware, methodHandler, at.MiddlewareHandler{})
			methodHandler.handler = Handler(func(c context.Context) {
				hdl.call(c)
			})
			middleware.methods = append(middleware.methods, methodHandler)
		}
	}
	return
}
TODO: controller method handler, middleware handler, and event handler, they all use the same way to achieve handler dispatch.
package web
import (
	"fmt"
	"github.com/fatih/camelcase"
	"github.com/kataras/iris"
	"github.com/rakyll/statik/fs"
	"hidevops.io/hiboot/pkg/app"
	"hidevops.io/hiboot/pkg/app/web/context"
	"hidevops.io/hiboot/pkg/app/web/webutils"
	"hidevops.io/hiboot/pkg/at"
	"hidevops.io/hiboot/pkg/factory"
	"hidevops.io/hiboot/pkg/inject/annotation"
	"hidevops.io/hiboot/pkg/log"
	"hidevops.io/hiboot/pkg/system"
	"hidevops.io/hiboot/pkg/utils/reflector"
	"hidevops.io/hiboot/pkg/utils/str"
	"net/http"
	"path"
	"reflect"
	"strings"
)
var httpMethods = []string{
	http.MethodGet,
	http.MethodHead,
	http.MethodPost,
	http.MethodPut,
	http.MethodPatch,
	http.MethodDelete,
	http.MethodConnect,
	http.MethodOptions,
	http.MethodTrace,
}
const (
	Any             = "ANY"
	RequestMapping  = "RequestMapping"
	ContextPathRoot = "/"
	UrlSep          = "/"
)
type Dispatcher struct {
	webApp *webApp
	configurableFactory factory.ConfigurableFactory
	SystemApp    *system.App
	SystemServer *system.Server
	ContextPathFormat string `value:"${server.context_path_format}" `
	methodSubscribers []*factory.MetaData
}
type requestMapping struct {
	Method string
	Value  string
}
type injectableMethod struct {
	method              *reflect.Method
	annotations         *annotation.Annotations
	handler             iris.Handler
	hasMethodAnnotation bool
	requestMapping      *requestMapping
}
type injectableObject struct {
	object      interface{}
	name        string
	pkgPath     string
	pathPrefix  string
	before      *injectableMethod
	after       *injectableMethod
	methods     []*injectableMethod
	annotations *annotation.Annotations
}
type Annotations struct {
	Fields []*annotation.Field
	Object interface{}
	Value  reflect.Value
}
func newDispatcher(webApp *webApp, configurableFactory factory.ConfigurableFactory) *Dispatcher {
	d := &Dispatcher{
		webApp:              webApp,
		configurableFactory: configurableFactory,
	}
	return d
}
func init() {
	app.Register(newDispatcher)
}
func (d *Dispatcher) parseAnnotation(object interface{}, method *reflect.Method) (ma *annotation.Annotations) {
	numIn := method.Type.NumIn()
	inputs := make([]reflect.Value, numIn)
	inputs[0] = reflect.ValueOf(object)
	for n := 1; n < numIn; n++ {
		typ := method.Type.In(n)
		iTyp := reflector.IndirectType(typ)
		if iTyp.Name() == "" && typ.Kind() == reflect.Struct {
			av := reflect.New(typ)
			avo := av.Interface()
			ma = annotation.GetAnnotations(avo)
			if ma != nil {
				_ = d.configurableFactory.InjectIntoObject(avo)
				break
			}
		}
	}
	return
}