spring学习
本文为学习笔记,参考传智播客spring2.5视频
一、控制反转(IOC):应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用本身转移到了外部容器,控制权的转移就是所谓的控制反转。
二、依赖注入(DI):在运行期,由外部容器动态地将依赖对象注入到组件中。网上看到的有比较容易理解的对依赖注入的描述:“平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。”
依赖注入有手工装配、自动装配两种形式。其中在实际使用中使用手工装配,自动装配会发生一些不可控现象。手工装配常用的有三种方式:
1、使用属性的setter方法注入(要求对要注入的属性必须设置set方法)
*基本类型对象注入:
<bean id="personService" class="com.ushareit.springMaven.service.impl.PersonServiceBean"> <property name="name" value="ushareit"></property> <property name="id" value="34"></property> </bean>
*注入其他bean有两种方式:
1、ref方式
<bean id="personDao" class="com.ushareit.springMaven.dao.impl.PersonDaoBean"></bean> <bean id="personService" class="com.ushareit.springMaven.service.impl.PersonServiceBean"> <property name="personDao" ref="personDao" ></property> </bean>
2、使用内部bean
<bean id="personService" class="com.ushareit.springMaven.service.impl.PersonServiceBean"> <property name="personDao"> <bean class = "com.ushareit.springMaven.dao.impl.PersonDaoBean"></bean> </property> </bean>
*集合类型Set的注入:
<property name="sets"> <set> <value>第一个</value> <value>第二个</value> <value>第三个</value> </set> </property>
*列表类型List注入:
<property name="lists"> <list> <value>list1</value> <value>list2</value> <value>list3</value> </list> </property>
*Property类型注入:
<property name="properties"> <props> <prop key="key1">value1</prop> <prop key="key2">value2</prop> <prop key="key3">value3</prop> </props> </property>
*Map类型注入:
<property name="maps"> <map> <entry key="key-1" value="value-1"></entry> <entry key="key-2" value="value-2"></entry> <entry key="key-3" value="value-3"></entry> </map> </property>
2、使用构造器注入
使用<constructor-arg>标签
<bean id="personDao" class="com.ushareit.springMaven.dao.impl.PersonDaoBean"></bean> <bean id="personService" class="com.ushareit.springMaven.service.impl.PersonServiceBean"> <constructor-arg index="0" type="com.ushareit.springMaven.dao.PersonDao" ref="personDao"></constructor-arg> <constructor-arg index="1" value="茄子快传"></constructor-arg> </bean>
并且需在构造器中对要注入的属性赋值。
public class PersonServiceBean implements PersonService { private PersonDao personDao; private String name; public PersonServiceBean(PersonDao personDao, String name) { this.personDao = personDao; this.name = name; } public void save() { personDao.add(); System.out.println(name); } }
3、使用Field注入(用于注解方式)
在java代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
三、使用spring的好处:
*降低组件之间的耦合度,实现软件各层之间的解耦。controller--->service--->dao
*可以使用spring容器提供的各种服务。如JMS服务、事务管理服务、spring core核心服务、持久化服务、其他服务。
*容器提供单例模式支持,开发人员无需自己再手动实现。
*采用AOP技术,很容易实现权限拦截、运行期监控等功能。
*使用众多辅助类,加速应用开发,如JdbcTemplate。
*对主流应用框架提供了很好集成支持,如JPA、hibernate、Struts等。
四、实例化spring容器常用的两种方式:
*在类路径下寻找配置文件来实例化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
*在文件系统路径下寻找配置文件来实例化容器
ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{"d:\\beans.xml"});
注:spring的配置文件可以指定多个,可以通过string数组引入
五、面向接口编程的思想
A s = new B();
一个对象实例只能赋值给与它类型相同的引用、或者父类(包括接口)的引用。
B是A的实现类,所以B的实例可以赋值给A的引用。
实例:确实的对象;引用:指向某一对象的名字。
耦合度:一个类(或者对象)对另一个类(或者对象)的依赖。指的是软件模块相互之间的关联,耦合度越高,这就说明软件的独立性越差。比方说,一个模块出现了问题,就可能牵连其他模块,导致其他模块的功能也不能正常运行。
s这个对象具有A接口规定的一切方法(B类里强制必须实现的)。
这样C、D、E、F类也可以实现A接口,如果想替换成C、D、E、F就很简单了,调用的时候还是用A接口规定的那些方法。
结合一些动态载入(例如spring的xml配置可以动态生成类),不会耦合了。
六、三种实例化bean的方式
1、使用类构造器实例化(约占90%)
<bean id="personService" class="cn.ushareit.service.impl.PersonServiceBean"></bean>
2、使用静态工厂方法实例化
<bean id="personService2" class="cn.ushareit.service.impl.PersonServiceBeanFactory" factory-method="createPersonServiceBean"></bean>
public class PersonServiceBeanFactory { public static PersonServiceBean createPersonServiceBean(){ return new PersonServiceBean(); } }
3、使用实例工厂方法实例化
<bean id="personServiceFactory" class="cn.ushareit.service.impl.PersonServiceBeanFactory"></bean> <bean id="personService3" factory-bean="personServiceFactory" factory-method="createPersonServiceBean2"></bean>
public class PersonServiceBeanFactory { public PersonServiceBean createPersonServiceBean2(){ return new PersonServiceBean(); } }
七、bean的作用域(scope属性)
* singleton
在每个Spring IOC容器中一个bean定义只有一个对象实例,相当于是单例模式。默认情况下会在容器启动时初始化bean。但我们可以指定bean节点的lazy_init="true"来延迟初始化bean,这时候,只有第一次获取bean才会初始化bean。如:<bean id="personService" class="cn.ushareit.service.impl.PersonServiceBean" lazy_init="true"></bean>。
如果想对所有bean都使用延迟初始化,可以在根节点beans设置default-lazy-init="true",如下<beans default-lazy-init="true"...>
* prototype
每次从容器获取bean都是新对象,即new。
八、指定bean的初始化方法和销毁方法
1、对于scope="singleton"的情况,在spring容器初始化的时候,bean就被初始化了。
2、对于scope="prototype"的情况,只有在spring容器初始化完成后,调用getBean方法的时候,bean才被初始化。
3、如果想保持spring容器中的bean是单例,还想延迟初始化bean,即在第一次获取bean的时候才初始化bean,就要靠lazy-init="true"(或default-lazy-init="true"全局)来控制。