这是我的笔记,有可能不对,望指正。
我们都知道Spring最著名的IOC(Inversion of Control),它的理念就是对象的创建由Spring容器来创建,那么相较于我们写Java的时候自己创建对象,这种方式就是控制反转,因为我们只是使用,而不再控制对象。
被实例,组装,及被Spring管理的Java对象就是bean。由Spring管理的bean之间的协作行为被称为装配(wiring)。
在Spring中,bean可以被定义为两种模式,单例singleton(默认),多例prototype。
所以@Autowired默认注入的是单例注入,单例类似于静态,具有全局唯一性。
一个类使用@Autowired,那么这个类必须由spring容器托管,就比如这个类要打上@Component或@Service的注解。一个由Spring容器代理的类不能有非Spring容器管理的私有成员变量。
我遇到的业务场景是,我要给A服务不同的Controller访问的路径的model中,放入B服务生成的Map令牌集合。
我要通过RestTemplate来请求B服务并带回结果信息。
此时的,错误代码:
public class CreateJwtUtil{
@Autowired
private RestTemplate restTemplate;
public static Map<String,String> getJwts(){
return restTemplate.postForObject(url,requestObject,Map.class);
}
}
// 此时的错误 我在非Spring管理的类中使用了@Autowired
调用这个方法的Controller
@Controller
public Controlelr{
@GetMapping("/test")
public String test(){
model.addAttribute("jwt",CreateJwtUtil.getJwts());
return "jsp";
}
}
解决方式一:
不依赖Spring容器
public class CreateJwtUtil{
private RestTemplate restTemplate;
public CreateJwtUtil(RestTemplate restTemplate){
this.restTemplate = restTemplate;
}
public static Map<String,String> getJwts(){
return restTemplate.postForObject(url,requestObject,Map.class);
}
//这种方式是单例的
}
调用的Controller
@Controller
public Controlelr{
@Autowired
private RestTemplate restTemplate;
@GetMapping("/test")
public String test(){
CreateJwtUtil util = new CreateJwtUtil(restTemplate);
model.addAttribute("jwt",util.getJwts());
return "jsp";
}
}
解决方式二:
依赖Spring容器
@Component
public class CreateJwtUtil{
@Autowired
private RestTemplate restTemplate;
public static Map<String,String> getJwts(){
return restTemplate.postForObject(url,requestObject,Map.class);
}
}
调用的Controller
@Controller
public Controlelr{
@Autowired
private CreateJwtUtil createJwtUtil;
@GetMapping("/test")
public String test(){
model.addAttribute("jwt",createJwtUtil.getJwts());
return "jsp";
}
}
这种模式还是单例。
我之前觉得这里应该用多例,但是按照面向对象来看,我只是用这个对象的方法,这个对象的属性没有改变,所以不是多例的使用场景。
多例注入的例子
方案一:
@Component
// @Scope默认是单例模式,即scope="singleton"
// prototype原型模式,每次获取Bean的时候会有一个新的实例
@Scope(value="prototype")
public class Test {
private String name = "7";
}
注入方式
@Autowired
private Test test;
@Autowired
private Test test1;
方案二(对象工厂):
@Component
// @Scope默认是单例模式,即scope="singleton"
// prototype原型模式,每次获取Bean的时候会有一个新的实例
@Scope(value="prototype")
public class Test {
private String name = "7";
}
注入方式
public class Controller{
@Autowired
private ObjectFactory<Test> test;
@GetMapping("/test")
public void test(){
this.test.getObject();
}
}
方案三(动态代理):
@Component
// @Scope默认是单例模式,即scope="singleton"
// prototype原型模式,每次获取Bean的时候会有一个新的实例
@Scope(value="prototype",proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Test {
private String name = "7";
}
共同学习,写下你的评论
评论加载中...
作者其他优质文章