为了账号安全,请及时绑定邮箱和手机立即绑定

Spring实际遇到的多例单例

标签:
Spring

这是我的笔记,有可能不对,望指正。
我们都知道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";
}
点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消