发表于: 2017-12-14 11:19:48

1 662


今天完成的事



【dubbo完美配置成功】


看似一张很简单的图,涉及的知识点相当的多。

明天再总结。总结不完就不总结了。


收获

 单例和多例的区别 :
单例多例需要搞明白这些问题:
     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();
   }
}

控制台输出

modle.User@42552cservice.userService@19e15c:serviceservice.ToolImpl@11a75a2:Tool Work
modle.User@210b5b
service.userService@19e15c:service
service.ToolImpl@170888e:Tool Work


遇到的问题

第一个bug

解决方案:使用Dubbo进行数据传递时,需让作为消息传递的类序列化。

第二个bug



百度文档http://blog.csdn.net/shutingwang/article/details/6594703

  问题:
        1.在Setter注入方式中,在beans包下的ProductBean中只加入一个带参

数的构造方法会如何?

        答:将会产生异常Spring异常与JVM异常
        Exception in thread "main" 

org.springframework.beans.factory.BeanCreationException:
        Error creating bean with name 'productBean' defined in file 
        

[/home/tarena/corejava/JSP/SpringPrj/./src/ioc/common/config/config.xm

l]: 
        Instantiation of bean failed; nested exception is
         org.springframework.beans.BeanInstantiationException: 
        Could not instantiate bean class 

[ioc.common.beans.ProductBean]: 
        No default constructor found; nested exception is 

java.lang.NoSuchMethodException:
        ioc.common.beans.ProductBean.<init>()
        //JVM异常        
        Caused by: java.lang.NoSuchMethodException: 

ioc.common.beans.ProductBean.<init>()
        
        Tips:强烈建议有不带参数的构造器


至于为什么

javabean相当于一个类,在它不定义任何构造方法的时候,系统提供了一个默认的无参数的构造方法。为何自己还要定义一个无参数的构造方法?


我的理解是

Bean实例在被Spring容器初始化的时候,就会被实例化,默认调用无参数的构造方法。(高亮注意,貌似和单例模式有关?)

当你创建含有参数的构造器时,系统不会生成默认的构造器,所以需要自己创建。

我解释的够清楚了吧。。。

明天的计划

任务8

禅道链接

http://task.ptteng.com/zentao/project-task-390.html


返回列表 返回列表
评论

    分享到