学习Spring札记一

学习Spring笔记一

Spring有规划作用,耦合度低、更容易测试、代码更清晰简单。没有Spring也能写项目,但是用了Spring项目会更加‘健康’。Spring官方言,只要你用的是Java语言,就能用Spring,可见Spring对于Java有多重要,和数据库一样重要。用了Spring的Java项目都会更加健壮。Spring致力于J2EE应用的各层解决方案(企业管理软件开发),它现在是大多数企业开发的一站式选择。除此之外Spring可以和已有框架无缝整合,充分为开发人员考虑,如果你想用别的框架就用,不想用可以用Spring提供的服务,Spring的社区非常强大。


Spring的核心就两个IOC和AOP,但Spring中包含很多优秀的设计模式,你在使用它的时候已经在提高自己了。


优势:提供了IOC容器、AOP、提供简易的服务抽象(把底层的技术进行了简单的封装,让其更好用,如JDBC)、集成管理各种框架



作为铺垫我们要先学设计模式,Spring涉及了以下设计模式

单例模式——>工厂模式——>IOC——>代理(静态代理、动态代理——动态代理的进阶是AOP)

这几个模式按顺序来学


单例模式

常用的有四种创建方式:lazy、eager、static、享元


单例的原则是:1.自己创建自己  2.私有化构造器  3.提供对外的访问方法


经典的单例有

Servlet是单例,被所有线程共享

Session也是单例,在一次会话中只有一个Session,它的单例不彻底,只限于当前会话,这次会话的东西只能这次会话中取出来,数据在下次会话就消失了

Application是最彻底的单例,放进去的数据,会一直在,直到服务器被重启。



lazy懒汉式单例

用的时候再实例化,节省了内存空间

public class LazySingleton{

private static LazySingleton lazySingleton = null;

private LazySingleton(){
super();
}


public static synchronized LazySingleton getInstance(){
if(lazySingleton == null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
*私有化构造器是为了不让别人实例化它

*synchronized 为防止多个线程同时进入这个方法对此类进行实例化,使用了synchronized ,这样的缺点是每次有多个线程执行这个方法,都会排除等待,影响性能,除了第一次实例化后,就不需要再创建这个实例了,之后的访问也就不需要再上同步锁。理想的状态是:第一次访问时用同步锁,创建好这个实例后,以后再访问此方法就是去取创建好的实例,这时不需要有synchronized ,这样多个线程能同时访问此方法,性能会高很多。 synchronized一定要加哦!



eager饿汉式单例

不管用不用都会创建,相比之下更占用空间

public class EagerSingleton{

private static EagerSingleton eagerSingleton = new EagerSingleton();

private EagerSingleton(){
super();
}

public static EagerSingleton getInstance(){
return eagerSingleton;
}
}



static静态内部类

它解决了Lazy的同步锁性能差问题,算是对Lazy的一种改进

public class StaticSingleton{

private StaticSingleton(){
super();
}

private static class Temp{   //静态内部类
public static StaticSingleton ss = new StaticSingleton();
}

public static StaticSingleton getInstance(){
return Temp.ss;
}
}
*静态内部类的特点

        1.用时再加载,有懒加载的特性,不访问getInstance就不会访问Temp.ss,就不会创建实例

        2.安全不影响性能,实例是静态变量,Java语法设定了静态变量只能初始化一次,所以不用担心多个线程同时创建实例,不需要加synchronized。那这之后的访问,不论多少个线程,都不会排队等待,提高了性能。



托管式(享元式)单例

像之前的daoFactory,提供一个容器,把对象都放在这里面new,用的时候从里面拿。


总结单例:虽然简单,但是有讲究,不同的人有不同的思维方式。用哪种方式实现单例,取决于你。


从数量上讨论这个类是什么类

a.想让这个类只有一个对象(单例类)

b.想让这个类有若干(10个或100个)对象 —— 想让这个类有若干个固定数量的对象,一般用在对稀有资源的控制,我们把这种称为“池”,如数据库连接池,线程池

c.或是任意个对象(就是普通类,可以随便new)


什么样的类应该被设计成单例?

服务类(无状态)类应被设计成单例:只需要提供对外的服务,不提供数据存储,如servlet、dao

数据类(有状态)类不应被设计成单例:数据会变,不能设计成单例。因为它的数据会变,需要不止一次的实例化,如struts2的action,和po


有状态类——>有成员变量,而且成员变量是可变的,如Strtus2的action

无状态类——>类里没有成员变量,或者成员变量是不可变的,或是单例的,如struts1的action,因为它是无状态的。


单例模式的作用

1.控制资源的使用,通过线程同步来控制资源的并发访问

2.控制实例产生的数量,起到节约资源的目的

3.作为通信媒介使用,也就是数据共享,两个线程通信,从同一个实例中取数据。

   数据库就是一个单例,一个线程把数据放到数据库中,另一个线程从数据库中取出来,数据放到同一个类里,才能达到数据传输的目的



————————题外——good answer——————

JSP四大作用域

page  当前页面,也就是只要跳到别的页面就失效了

request  一次请求,简单的理解就是一次请求范围内有效

session  一次会话,只要当前页面没有被关闭(没有被程序强制清除),不管怎么跳转都是有效的(比如360浏览器,你清除此页后,访问记录只是被标记为删除,你点击还能访问,除非你把浏览器关了)

application  服务器,只要服务器没有重启(没有被程序强制清除),数据就有效


JSP九大内置对象            对应servlet中的java对象

page                                    this

pageContext                      PageContext

request                                HttpServletRequest

response                             HttpServletResponse

config                                   ServletConfig

exception                            Throwable

out                                        JspWrite

session                                HttpSession

application                          ServletContext


单例end————————————————————————————————



工厂模式

为什么要有工厂模式

当系统扩展需要添加新的产品对象时,使用工厂模式的项目仅仅需要添加一个具体对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放—封闭”原则。代码实现上是把new的过程放在一个类里,通过增加判断的结点来实现。


工厂模式分

1.简单工厂模式  一个对象,比如以前的dbutil

2.*工厂方法模式  一系列对象,比如下面的例子,可以根据需要换实现方法

3.抽象方法模式   高大神说比较复杂,挺少有人这么用




实例

1.创建两个包action、dao


2.dao包下创建接口UserDao,接口内容如下

    public interface UserDao{

   void add();

    }


3.创建dao.impl包,并在包下创建接口的实现类UserDaoImpl4MySql,实现类内容如下

   pulic class UserDaoImpl4MySql  implements UserDao{

public void add(){

System.out.println(" I'M MySQL");

}

   }


4.在dao.impl包下创建UserDaoImpl4Oracle类,并实现UserDao接口

    public class UserDaoImpl4Oracle implements UserDao{

public void add(){

System.out.println("I',M Oracle");

}

    }

   //3和4的实现类实现同一个接口UserDao,意味着可以根据需要替换实现类



5.在dao.impl包下,创建一个UserDaoFactory类来封装所有实现类,内容如下

    public class UserDaoFactory{

   public static UserDao getInstance(){

String dbtype = "mysql";      //模拟从db.properties取出,实际应该是从db.properties中读取出dbtype

if("mysql".equals(dbtype)){

return new UserDaoImpl4Mysql();

}else if("oracle".equals(dbtype)){

return new UserDaoImpl4Oracle();

}else {

return null;

}

}

     }



6.在action下创建UserAction类进行测试工厂方法是否可以“热插拨”变更实现类,代码如下

    public class UserAction{

private UserDao userDao = UserDaoFactory.getInstance(); //父类引用指向子类方法,想换实现类时,只要把这里改了,这个步骤后续还会把它另外拿出来,放在spring的IOC容器中

public String add(){

userDao.add();

return null;

}

public static void main(String[ ] args){

UserAction userAction = new UserAction();

userAction.add();

}

     }

//接下来运行UserAction,测试UserDao接口的实现类是否通过工厂方法模式实现了自由替换。



工厂模式end————————————————————