惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
AWS News Blog
AWS News Blog
Google DeepMind News
Google DeepMind News
U
Unit 42
博客园 - 叶小钗
博客园 - 聂微东
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
D
DataBreaches.Net
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Jina AI
Jina AI
美团技术团队
The Cloudflare Blog
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
S
Schneier on Security
C
Check Point Blog
Project Zero
Project Zero
The Hacker News
The Hacker News
Scott Helme
Scott Helme
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Cisco Talos Blog
Cisco Talos Blog
P
Privacy International News Feed
SecWiki News
SecWiki News
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
F
Fortinet All Blogs
博客园 - 三生石上(FineUI控件)
H
Help Net Security
TaoSecurity Blog
TaoSecurity Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Last Week in AI
Last Week in AI
P
Privacy & Cybersecurity Law Blog
Forbes - Security
Forbes - Security
G
GRAHAM CLULEY
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity
A
About on SuperTechFans
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
大猫的无限游戏
大猫的无限游戏
T
Troy Hunt's Blog
H
Hacker News: Front Page
Vercel News
Vercel News

博客园 - PointNet

log4j2发送消息至Kafka log4j2自定义Appender(输出到文件/RPC服务中) log4j 不同模块输出到不同的文件 shell之磁盘容量检查,配合crontab可以定时清理磁盘 spring注解之@profile How to do conditional auto-wiring in Spring? MyBatis传入参数为集合 list 数组 map写法 Spring Boot @Autowired 没法自动注入的问题 mysql5.5 uuid做主键与int做主键的性能实测 dom4j解析xml字符串实例 Spring中Bean的五个作用域 【总结】瞬时高并发(秒杀/活动)Redis方案 浅谈分布式事务 基于Redis实现分布式锁 MySQL事务隔离级别详解 Redis学习手册(Sorted-Sets数据类型) Redis的快照持久化-RDB与AOF Redis - 事务 ArrayList、Vector、HashMap、HashTable、HashSet的默认初始容量、加载因子、扩容增量
spring自动注入是单例还是多例?单例如何注入多例?
PointNet · 2017-09-04 · via 博客园 - PointNet

     1. 什么是单例多例;

     2. 如何产生单例多例;

     3. 为什么要用单例多例

     4. 什么时候用单例,什么时候用多例;

1. 什么是单例、多例:

     所谓单例就是所有的请求都用一个对象来处理,比如我们常用的service和dao层的对象通常都是单例的,而多例则指每个请求用一个新的对象来处理,比如action;

     单例模式和多例模式说明:

     1. 单例模式和多例模式属于对象模式。

     2. 单例模式的对象在整个系统中只有一份,多例模式可以有多个实例。

     3. 它们都不对外提供构造方法,即构造方法都为私有。

2. 如何产生单例、多例:

    在通用的SSH中,单例在spring中是默认的,如果要产生多例,则在配置文件的bean中添加scope="prototype";

3. 为什么用单例、多例:

    之所以用单例,是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存;

   之所以用多例,是为了防止并发问题;即一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理;

    用单例和多例的标准只有一个:

    

当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例;

4. 何时用单例?何时用多例?

    对于struts2来说,action必须用多例,因为action本身含有请求参数的值,即可改变的状态;

    而对于STRUTS1来说,action则可用单例,因为请求参数的值是放在actionForm中,而非action中的;

    另外要说一下,并不是说service或dao一定是单例,标准同第3点所讲的,就曾见过有的service中也包含了可改变的状态,同时执行方法也依赖该状态,但一样用的单例,这样就会出现隐藏的BUG,而并发的BUG通常很难重现和查找;

     

 spring生成对象默认是单例的。通过scope属性可以更改为多例

<bean id="user" class="modle.User" scope="prototype">  </bean>

现在又这么一种情况.

User类调用一个service, 这个service又调用一个tool。

有时我们希望User是多例的,service是单例的,而tool又是多例的。

很自然地想法是配置文件这些写

<bean id="user" class="modle.User" scope="prototype">   

     <property name="service" ref="userservice"></property> 

</bean>   

<bean id="userservice" class="service.userService" >   

     <property name="tool" ref="tool"></property> 

</bean>   

<bean id="tool" class="service.ToolImpl" scope="prototype">

</bean>

但是这种写法是错误的! 不能使用spring的自动注入!

由于service是单例的,所以这种方法的结果是:User多例,service和tool都是单例。(为什么?)

官网文档:

4.5.3 Singleton beans with prototype-bean dependencies

When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.

However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies. If you need a new instance of a prototype bean at runtime more than once, see Section 4.4.6, “Method injection”

正确的写法是,是每次调用tool时都生成一个新的tool对象。但是我们又不能手动new一个,要借助BeanFactory

public class User {

  private userService service;

  private int age;

  private Date date;

  private String name;

UserService 通过实现 BeanFactoryAware 接口来获得factory

由于不使用spring的自动注入,set方法要去掉!

public class userService implements BeanFactoryAware{   

  private Tool tool;

  private BeanFactory factory;
  public void service(){
    this.tool = (Tool)factory.getBean("tool");
    System.out.println(this+":service");
    tool.work();
  }
  public Tool getTool() {
        return tool;
  }

// public void setTool(Tool tool) {//        

// this.tool = (Tool)factory.getBean("tool");// } 

public void setBeanFactory(BeanFactory f) throws BeansException {

    factory = f;
  }
 
}

配置文件,不能再使用注入。因此要把tool对象的注入去掉!

<bean id="user" class="modle.User" scope="prototype">   

     <property name="service" ref="userservice"></property> 

</bean>   

<bean id="userservice" class="service.userService" > 

</bean>   

<bean id="tool" class="service.ToolImpl" scope="prototype">

</bean>

public interface Tool { 

     public void work();

}

public class ToolImpl implements Tool{

  public void work() {
    System.out.println(this+":Tool Work");

  }

}

测试类:

public class Test {
  public static void main(String[] args) {
    ClassPathResource res = new ClassPathResource("applicationContext.xml");
    XmlBeanFactory factory = new XmlBeanFactory(res);
    User user = (User)factory.getBean("user");
    User user2 =  (User)factory.getBean("user");
        System.out.println(user);
    user.getService().service();
    System.out.println();
    System.out.println(user2);
    user2.getService().service();
  }
}

Output:

modle.User@42552c
service.userService@19e15c:service
service.ToolImpl@11a75a2:Tool Work

modle.User@210b5b
service.userService@19e15c:service
service.ToolImpl@170888e:Tool Work