Spring define a bean in session scope with java co

2019-07-18 02:27发布

问题:

I would like to use a bean in session scope, but I receive an error:

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [C:\Program Files\Apache Software Foundation\Tomcat 8.0\webapps\testRestService\WEB-INF\classes\test\server\config\AppConfig.class];
nested exception is java.lang.annotation.AnnotationFormatError: Invalid default: public abstract org.springframework.beans.factory.annotation.Autowire org.springframework.config.java.annotation.Bean.autowire()

The Person Bean:

public class Person {
//This is a Pojo
//...
}

The AppConfig:

@Configuration
@EnableWebMvc
@ComponentScan("test.server")
public class AppConfig extends WebMvcConfigurerAdapter {

    @Bean(scope = DefaultScopes.SESSION)
    @ScopedProxy
    public Person getPerson() {
        return new Person();
    }
}

The Person Sercive:

@Component
public class PersonService implements IPersonService {

    @Autowired
    protected Person person;

    @Override
    public void setPerson(Person person) {
        this.person = person;
    }

    @Override
    public Person getPerson() {
        return this.person;
    }
}

The PersonController:

@RestController()
@RequestMapping("/person")
public class PersonController {

    @Autowired
    private IPersonService personService;

    @InitBinder
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
        binder.registerCustomEditor(Person.class, new GenericEditor<Person>(Person.class));
    }

    @RequestMapping(value = "/setPerson", method = RequestMethod.GET)
    public String setPerson(@RequestParam(value = "person") Person person) {
         this.personService.setPerson(person);
         return "Person: " + person + " saved.";
    }

    @RequestMapping(value = "/getPerson", method = RequestMethod.GET)
    public Person getPerson() {
         return this.personService.getPerson();
    }
}

I tried to use @Scope("session") on the Person bean, in this case I did not use the @ScopedProxy annotation in appconfig and used the @org.springframework.context.annotation.Bean("person") instead of org.springframework.config.java.annotation.Bean(scope = DefaultScopes.SESSION). In this case I didn't receive an error, but the Person bean wasn't in the session scope when I tested it.

Thanks for the help.

回答1:

Session level beans are supported through JDK dynamic proxies. The following modifications are required in your code:

  • remove the getPerson() method from the AppConfig class
  • do not autowire your bean in PersonService, just instantiate it with it's default constructor
  • annotate the PersonService with the following:
    • @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)


回答2:

Annotate the classes which bean has scope as follow:

@Scope(value = [scope], proxyMode = ScopedProxyMode.TARGET_CLASS)

Proxy Mode TARGET_CLASS: is used for creating AOP proxy of the bean. We must do it when injecting short lived bean scope (request, session…) to long lived bean scope (singleton, prototype) or injecting prototype to singleton scope.

@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class Address {
    private String address = "US";

    public Address() {
        System.out.println("Create new Address: " + this.address);
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

}


@Component
public class Customer {

    @Autowired
    private Address address;

    public String getCustomerAddress(){
        return address.getAddress();
    }

    public void setCustomerAddress(String address){
        this.address.setAddress(address);
    }


}