如何使用spring

时间:2016-03-16 09:20:29

标签: java spring

我有一个spring应用程序,并希望在运行时根据请求创建一个bean,将其注入另一个类,就像CDI的@Producer一样。

我的bean只是一个简单的POJO:

public class UserDetails {

    private String name;

    // getter / setter ... 

    public UserDetails(String name) {
        this.name = name;
    }
}

我的制作人类看起来像这样:

@Configuration
public class UserFactory {

    @Bean
    @Scope("request")
    public UserDetails createUserDetails() {
        // this method should be called on every request
        String name = SecurityContextHolder.getContext()
                        .getAuthentication().getPrincipal(); // get some user details, just an example (I am aware of Principal)

        // construct a complex user details object here
        return new UserDetails(name)
    }
}

这是应该注入UserDetails实例的类:

@RestController
@RequestMapping(value = "/api/something")
public class MyResource {

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<String> getSomething(UserDetails userDetails) {
        // the userdetails should be injected here per request, some annotations missing?

        // do something
    }
}

问题是Spring在运行时抱怨没有默认构造函数(当然)。

Failed to instantiate [UserDetails]: No default constructor found

但这是有意的,我想调用我自己的工厂让它来处理实例化。

我怎样才能做到这一点?为什么UserFactory从未被调用?

3 个答案:

答案 0 :(得分:10)

基本上你没有使用你的范围代理。您不能将范围代理注入方法,您必须将其注入您的控制器。

public List<String> getSomething(UserDetails userDetails) { ... }

这会导致spring试图通过反射创建UserDetails的新实例,它不会注入你的scoped bean。因此,它抱怨你需要一个默认的无参数构造函数。

相反,您应该做的是将依赖关系连接到控制器而不是控制器方法。

@RestController
@RequestMapping(value = "/api/something")
public class MyResource {

    @Autowired
    private UserDetails userDetails;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<String> getSomething() {
        // the userdetails should be injected here per request, some annotations missing?

        // do something
    }
}

我们的想法是UserDetails是一个作用域代理,使用时将使用已存在的对象或基于@Bean方法创建一个新对象。

另外,@Scope中的UserFactory注释必须按如下方式进行修改才能正常工作:

@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) 

答案 1 :(得分:1)

您正在尝试在单例bean上注入请求范围的bean。 您需要使用UserDetails

的代理
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES) 

答案 2 :(得分:0)

public class UserDetails { private String name; // getter / setter ... public UserDetails() { } public UserDetails(String name) { this.name = name; } } 中需要一个无参数的构造函数。

<script>
  var testApp = angular.module('testApp', []);

  testApp.directive('dynamic', function ($compile) {
    return {
      restrict: 'A',
      replace: true,
      link: function (scope, ele, attrs) {
        scope.$watch(attrs.dynamic, function(html) {
          ele.html(html);
          $compile(ele.contents())(scope);
        });
      }
    };
  });

  testApp.controller('PhoneListCtrl', function ($scope) {

  // Initializace text
  var inlinetext = 'Lorem ipsum dolor form sit amet, consectetur adipiscing elit. Vivamus in form ultricies ipsum. Quisque finibus lacus neque, sed tempor lectus form gravida nec. Nam egestas dui vel elit lacini';

  // Replace string and bind it to directive
  $scope.html = inlinetext.replace('form', '<input type="text" ng-model="demo">');
});
</script>