inject.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. package inject
  2. // facebook inject
  3. // source https://github.com/facebookarchive/inject
  4. import (
  5. "bytes"
  6. "fmt"
  7. "math/rand"
  8. "reflect"
  9. )
  10. // Logger allows for simple logging as inject traverses and populates the
  11. // object graph.
  12. type Logger interface {
  13. Debugf(format string, v ...interface{})
  14. }
  15. // Populate is a short-hand for populating a graph with the given incomplete
  16. // object values.
  17. func Populate(values ...interface{}) error {
  18. var g Graph
  19. for _, v := range values {
  20. if err := g.Provide(&Object{Value: v}); err != nil {
  21. return err
  22. }
  23. }
  24. return g.Populate()
  25. }
  26. // An Object in the Graph.
  27. type Object struct {
  28. Value interface{}
  29. Name string // Optional
  30. Complete bool // If true, the Value will be considered complete
  31. Fields map[string]*Object // Populated with the field names that were injected and their corresponding *Object.
  32. reflectType reflect.Type
  33. reflectValue reflect.Value
  34. private bool // If true, the Value will not be used and will only be populated
  35. created bool // If true, the Object was created by us
  36. embedded bool // If true, the Object is an embedded struct provided internally
  37. }
  38. // String representation suitable for human consumption.
  39. func (o *Object) String() string {
  40. var buf bytes.Buffer
  41. fmt.Fprint(&buf, o.reflectType)
  42. if o.Name != "" {
  43. fmt.Fprintf(&buf, " named %s", o.Name)
  44. }
  45. return buf.String()
  46. }
  47. func (o *Object) addDep(field string, dep *Object) {
  48. if o.Fields == nil {
  49. o.Fields = make(map[string]*Object)
  50. }
  51. o.Fields[field] = dep
  52. }
  53. // The Graph of Objects.
  54. type Graph struct {
  55. Logger Logger // Optional, will trigger debug logging.
  56. unnamed []*Object
  57. unnamedType map[reflect.Type]bool
  58. named map[string]*Object
  59. }
  60. // GetObjectByName 根据name获取对象
  61. func (g *Graph) GetObjectByName(name string) (interface{}, error) {
  62. existing := g.named[name]
  63. if existing == nil {
  64. return nil, fmt.Errorf("did not find object named %s", name)
  65. }
  66. return existing.Value, nil
  67. }
  68. // Provide objects to the Graph. The Object documentation describes
  69. // the impact of various fields.
  70. func (g *Graph) Provide(objects ...*Object) error {
  71. for _, o := range objects {
  72. o.reflectType = reflect.TypeOf(o.Value)
  73. o.reflectValue = reflect.ValueOf(o.Value)
  74. if o.Fields != nil {
  75. return fmt.Errorf(
  76. "fields were specified on object %s when it was provided",
  77. o,
  78. )
  79. }
  80. if o.Name == "" {
  81. if !isStructPtr(o.reflectType) {
  82. return fmt.Errorf(
  83. "expected unnamed object value to be a pointer to a struct but got type %s "+
  84. "with value %v",
  85. o.reflectType,
  86. o.Value,
  87. )
  88. }
  89. if !o.private {
  90. if g.unnamedType == nil {
  91. g.unnamedType = make(map[reflect.Type]bool)
  92. }
  93. if g.unnamedType[o.reflectType] {
  94. return fmt.Errorf(
  95. "provided two unnamed instances of type *%s.%s",
  96. o.reflectType.Elem().PkgPath(), o.reflectType.Elem().Name(),
  97. )
  98. }
  99. g.unnamedType[o.reflectType] = true
  100. }
  101. g.unnamed = append(g.unnamed, o)
  102. } else {
  103. if g.named == nil {
  104. g.named = make(map[string]*Object)
  105. }
  106. if g.named[o.Name] != nil {
  107. return fmt.Errorf("provided two instances named %s", o.Name)
  108. }
  109. g.named[o.Name] = o
  110. }
  111. if g.Logger != nil {
  112. if o.created {
  113. g.Logger.Debugf("created %s", o)
  114. } else if o.embedded {
  115. g.Logger.Debugf("provided embedded %s", o)
  116. } else {
  117. g.Logger.Debugf("provided %s", o)
  118. }
  119. }
  120. }
  121. return nil
  122. }
  123. // Populate the incomplete Objects.
  124. func (g *Graph) Populate() error {
  125. for _, o := range g.named {
  126. if o.Complete {
  127. continue
  128. }
  129. if err := g.populateExplicit(o); err != nil {
  130. return err
  131. }
  132. }
  133. // We append and modify our slice as we go along, so we don't use a standard
  134. // range loop, and do a single pass thru each object in our graph.
  135. i := 0
  136. for {
  137. if i == len(g.unnamed) {
  138. break
  139. }
  140. o := g.unnamed[i]
  141. i++
  142. if o.Complete {
  143. continue
  144. }
  145. if err := g.populateExplicit(o); err != nil {
  146. return err
  147. }
  148. }
  149. // A Second pass handles injecting Interface values to ensure we have created
  150. // all concrete types first.
  151. for _, o := range g.unnamed {
  152. if o.Complete {
  153. continue
  154. }
  155. if err := g.populateUnnamedInterface(o); err != nil {
  156. return err
  157. }
  158. }
  159. for _, o := range g.named {
  160. if o.Complete {
  161. continue
  162. }
  163. if err := g.populateUnnamedInterface(o); err != nil {
  164. return err
  165. }
  166. }
  167. return nil
  168. }
  169. func (g *Graph) populateExplicit(o *Object) error {
  170. // Ignore named value types.
  171. if o.Name != "" && !isStructPtr(o.reflectType) {
  172. return nil
  173. }
  174. StructLoop:
  175. for i := 0; i < o.reflectValue.Elem().NumField(); i++ {
  176. field := o.reflectValue.Elem().Field(i)
  177. fieldType := field.Type()
  178. fieldTag := o.reflectType.Elem().Field(i).Tag
  179. fieldName := o.reflectType.Elem().Field(i).Name
  180. tag, err := parseTag(string(fieldTag))
  181. if err != nil {
  182. return fmt.Errorf(
  183. "unexpected tag format `%s` for field %s in type %s",
  184. string(fieldTag),
  185. o.reflectType.Elem().Field(i).Name,
  186. o.reflectType,
  187. )
  188. }
  189. // Skip fields without a tag.
  190. if tag == nil {
  191. continue
  192. }
  193. // Cannot be used with unexported fields.
  194. if !field.CanSet() {
  195. return fmt.Errorf(
  196. "inject requested on unexported field %s in type %s",
  197. o.reflectType.Elem().Field(i).Name,
  198. o.reflectType,
  199. )
  200. }
  201. // Inline tag on anything besides a struct is considered invalid.
  202. if tag.Inline && fieldType.Kind() != reflect.Struct {
  203. return fmt.Errorf(
  204. "inline requested on non inlined field %s in type %s",
  205. o.reflectType.Elem().Field(i).Name,
  206. o.reflectType,
  207. )
  208. }
  209. // Don't overwrite existing values.
  210. if !isNilOrZero(field, fieldType) {
  211. continue
  212. }
  213. // Named injects must have been explicitly provided.
  214. if tag.Name != "" {
  215. existing := g.named[tag.Name]
  216. if existing == nil {
  217. return fmt.Errorf(
  218. "did not find object named %s required by field %s in type %s",
  219. tag.Name,
  220. o.reflectType.Elem().Field(i).Name,
  221. o.reflectType,
  222. )
  223. }
  224. if !existing.reflectType.AssignableTo(fieldType) {
  225. return fmt.Errorf(
  226. "object named %s of type %s is not assignable to field %s (%s) in type %s",
  227. tag.Name,
  228. fieldType,
  229. o.reflectType.Elem().Field(i).Name,
  230. existing.reflectType,
  231. o.reflectType,
  232. )
  233. }
  234. field.Set(reflect.ValueOf(existing.Value))
  235. if g.Logger != nil {
  236. g.Logger.Debugf(
  237. "assigned %s to field %s in %s",
  238. existing,
  239. o.reflectType.Elem().Field(i).Name,
  240. o,
  241. )
  242. }
  243. o.addDep(fieldName, existing)
  244. continue StructLoop
  245. }
  246. // Inline struct values indicate we want to traverse into it, but not
  247. // inject itself. We require an explicit "inline" tag for this to work.
  248. if fieldType.Kind() == reflect.Struct {
  249. if tag.Private {
  250. return fmt.Errorf(
  251. "cannot use private inject on inline struct on field %s in type %s",
  252. o.reflectType.Elem().Field(i).Name,
  253. o.reflectType,
  254. )
  255. }
  256. if !tag.Inline {
  257. return fmt.Errorf(
  258. "inline struct on field %s in type %s requires an explicit \"inline\" tag",
  259. o.reflectType.Elem().Field(i).Name,
  260. o.reflectType,
  261. )
  262. }
  263. err := g.Provide(&Object{
  264. Value: field.Addr().Interface(),
  265. private: true,
  266. embedded: o.reflectType.Elem().Field(i).Anonymous,
  267. })
  268. if err != nil {
  269. return err
  270. }
  271. continue
  272. }
  273. // Interface injection is handled in a second pass.
  274. if fieldType.Kind() == reflect.Interface {
  275. continue
  276. }
  277. // Maps are created and required to be private.
  278. if fieldType.Kind() == reflect.Map {
  279. if !tag.Private {
  280. return fmt.Errorf(
  281. "inject on map field %s in type %s must be named or private",
  282. o.reflectType.Elem().Field(i).Name,
  283. o.reflectType,
  284. )
  285. }
  286. field.Set(reflect.MakeMap(fieldType))
  287. if g.Logger != nil {
  288. g.Logger.Debugf(
  289. "made map for field %s in %s",
  290. o.reflectType.Elem().Field(i).Name,
  291. o,
  292. )
  293. }
  294. continue
  295. }
  296. // Can only inject Pointers from here on.
  297. if !isStructPtr(fieldType) {
  298. return fmt.Errorf(
  299. "found inject tag on unsupported field %s in type %s",
  300. o.reflectType.Elem().Field(i).Name,
  301. o.reflectType,
  302. )
  303. }
  304. // Unless it's a private inject, we'll look for an existing instance of the
  305. // same type.
  306. if !tag.Private {
  307. for _, existing := range g.unnamed {
  308. if existing.private {
  309. continue
  310. }
  311. if existing.reflectType.AssignableTo(fieldType) {
  312. field.Set(reflect.ValueOf(existing.Value))
  313. if g.Logger != nil {
  314. g.Logger.Debugf(
  315. "assigned existing %s to field %s in %s",
  316. existing,
  317. o.reflectType.Elem().Field(i).Name,
  318. o,
  319. )
  320. }
  321. o.addDep(fieldName, existing)
  322. continue StructLoop
  323. }
  324. }
  325. }
  326. newValue := reflect.New(fieldType.Elem())
  327. newObject := &Object{
  328. Value: newValue.Interface(),
  329. private: tag.Private,
  330. created: true,
  331. }
  332. // Add the newly ceated object to the known set of objects.
  333. err = g.Provide(newObject)
  334. if err != nil {
  335. return err
  336. }
  337. // Finally assign the newly created object to our field.
  338. field.Set(newValue)
  339. if g.Logger != nil {
  340. g.Logger.Debugf(
  341. "assigned newly created %s to field %s in %s",
  342. newObject,
  343. o.reflectType.Elem().Field(i).Name,
  344. o,
  345. )
  346. }
  347. o.addDep(fieldName, newObject)
  348. }
  349. return nil
  350. }
  351. func (g *Graph) populateUnnamedInterface(o *Object) error {
  352. // Ignore named value types.
  353. if o.Name != "" && !isStructPtr(o.reflectType) {
  354. return nil
  355. }
  356. for i := 0; i < o.reflectValue.Elem().NumField(); i++ {
  357. field := o.reflectValue.Elem().Field(i)
  358. fieldType := field.Type()
  359. fieldTag := o.reflectType.Elem().Field(i).Tag
  360. fieldName := o.reflectType.Elem().Field(i).Name
  361. tag, err := parseTag(string(fieldTag))
  362. if err != nil {
  363. return fmt.Errorf(
  364. "unexpected tag format `%s` for field %s in type %s",
  365. string(fieldTag),
  366. o.reflectType.Elem().Field(i).Name,
  367. o.reflectType,
  368. )
  369. }
  370. // Skip fields without a tag.
  371. if tag == nil {
  372. continue
  373. }
  374. // We only handle interface injection here. Other cases including errors
  375. // are handled in the first pass when we inject pointers.
  376. if fieldType.Kind() != reflect.Interface {
  377. continue
  378. }
  379. // Interface injection can't be private because we can't instantiate new
  380. // instances of an interface.
  381. if tag.Private {
  382. return fmt.Errorf(
  383. "found private inject tag on interface field %s in type %s",
  384. o.reflectType.Elem().Field(i).Name,
  385. o.reflectType,
  386. )
  387. }
  388. // Don't overwrite existing values.
  389. if !isNilOrZero(field, fieldType) {
  390. continue
  391. }
  392. // Named injects must have already been handled in populateExplicit.
  393. if tag.Name != "" {
  394. panic(fmt.Sprintf("unhandled named instance with name %s", tag.Name))
  395. }
  396. // Find one, and only one assignable value for the field.
  397. var found *Object
  398. for _, existing := range g.unnamed {
  399. if existing.private {
  400. continue
  401. }
  402. if existing.reflectType.AssignableTo(fieldType) {
  403. if found != nil {
  404. return fmt.Errorf(
  405. "found two assignable values for field %s in type %s. one type "+
  406. "%s with value %v and another type %s with value %v",
  407. o.reflectType.Elem().Field(i).Name,
  408. o.reflectType,
  409. found.reflectType,
  410. found.Value,
  411. existing.reflectType,
  412. existing.reflectValue,
  413. )
  414. }
  415. found = existing
  416. field.Set(reflect.ValueOf(existing.Value))
  417. if g.Logger != nil {
  418. g.Logger.Debugf(
  419. "assigned existing %s to interface field %s in %s",
  420. existing,
  421. o.reflectType.Elem().Field(i).Name,
  422. o,
  423. )
  424. }
  425. o.addDep(fieldName, existing)
  426. }
  427. }
  428. // If we didn't find an assignable value, we're missing something.
  429. if found == nil {
  430. return fmt.Errorf(
  431. "found no assignable value for field %s in type %s",
  432. o.reflectType.Elem().Field(i).Name,
  433. o.reflectType,
  434. )
  435. }
  436. }
  437. return nil
  438. }
  439. // Objects returns all known objects, named as well as unnamed. The returned
  440. // elements are not in a stable order.
  441. func (g *Graph) Objects() []*Object {
  442. objects := make([]*Object, 0, len(g.unnamed)+len(g.named))
  443. for _, o := range g.unnamed {
  444. if !o.embedded {
  445. objects = append(objects, o)
  446. }
  447. }
  448. for _, o := range g.named {
  449. if !o.embedded {
  450. objects = append(objects, o)
  451. }
  452. }
  453. // randomize to prevent callers from relying on ordering
  454. for i := 0; i < len(objects); i++ {
  455. j := rand.Intn(i + 1)
  456. objects[i], objects[j] = objects[j], objects[i]
  457. }
  458. return objects
  459. }
  460. var (
  461. injectOnly = &tag{}
  462. injectPrivate = &tag{Private: true}
  463. injectInline = &tag{Inline: true}
  464. )
  465. type tag struct {
  466. Name string
  467. Inline bool
  468. Private bool
  469. }
  470. func parseTag(t string) (*tag, error) {
  471. found, value, err := Extract("inject", t)
  472. if err != nil {
  473. return nil, err
  474. }
  475. if !found {
  476. return nil, nil
  477. }
  478. if value == "" {
  479. return injectOnly, nil
  480. }
  481. if value == "inline" {
  482. return injectInline, nil
  483. }
  484. if value == "private" {
  485. return injectPrivate, nil
  486. }
  487. return &tag{Name: value}, nil
  488. }
  489. func isStructPtr(t reflect.Type) bool {
  490. return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
  491. }
  492. func isNilOrZero(v reflect.Value, t reflect.Type) bool {
  493. switch v.Kind() {
  494. default:
  495. return reflect.DeepEqual(v.Interface(), reflect.Zero(t).Interface())
  496. case reflect.Interface, reflect.Ptr:
  497. return v.IsNil()
  498. }
  499. }