spring学习心得(一)
Spring核心内容为一种叫做控制反转(IoC:Inversion of Control)的设计思想,控制反转的意思通俗讲,就是将面向对象编程中创建对象和处理对象间依赖关系的过程交给第三方来管理,也就是尽量减少new对象的方式创建对象,所谓控制反转就是:获得依赖对象的方式反转了。实现控制反转的方法包含:DI(Dependency Injection:依赖注入),依赖查找。依赖注入又分为:Interface Injection(type 1),Setter Injection(type 2),Constructor Injection(type 3),即接口注入、配置注入、控制注入
ioc是目的,di是手段。ioc是指让生成类的方式由传统方式(new)反过来,既程序员不调用new,需要类的时候由框架注入(di),是同一件不同层面的解读。
依赖注入的好处:在项目中应用DI,你会发现你的代码会变得异常简单并且更容易理解和测试。Spring框架提供了骨架,你只要提供肉就可以了,你的肉在骨架中被调用,这就是控制反转的意义。
图三为IoC要达到的一种理想状态
IoC是Spring的核心内容,实现控制反转,可以通过XML配置、注解方式等,Spring容器在初始化的时候先读取XML配置文件,根据配置文件和元数据(POJO,对应于MVC的DAO数据访问接口)创建与组织对象存入到容器当中,等到程序需要的时候从IoC容器中取出使用

采用XML方式配置Bean的时候,Bean的定义信息和实现方式是分离的,采用注解的方式的话,将二者结合在一起Bean的定义信息直接以注解的方式定义在实现类中,从而打到零配置的目的,这时候XML中只需要配置好需要扫描的文件夹即可
一、使用XML方式实现IoC
第一步:引入Spring依赖的jar包:

第二步:新增一个XML配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userdao" class="com.lml.dao.UserDAO"></bean> </beans>
第三步:创建DAO接口及实现类(及数据访问接口和数据访问实现类)
package com.lml.dao; public interface IUserDAO { public String addUser(String userName); }
package com.lml.dao; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Repository; public class UserDAO implements IUserDAO{ private static Log log = LogFactory.getLog(IUserDAO.class); public String addUser(String userName) { log.debug("测试:添加图书" + userName + "成功"); return "添加图书" + userName + "成功"; } }
第四步:创建业务类
package com.lml.service; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lml.dao.UserDAO; public class UserService { private static Log log = LogFactory.getLog(UserService.class); UserDAO userDAO; public void storeUser(String userName){ ApplicationContext ac = new ClassPathXmlApplicationContext("IOCBeans01.xml"); userDAO = (UserDAO)ac.getBean("userdao"); String result = userDAO.addUser(userName); log.debug("result=" + result); } }
第五步:单元测试
package com.lml.test; import org.junit.Test; import com.lml.service.UserService; public class Test01 { @org.junit.Test public void testStoreUser(){ UserService userService = new UserService(); userService.storeUser("李蒙龙"); } }
本例子业务类中通过获取配置文件中的Bean(配置文件已经将数据访问实现类转换为容器管理的bean),从而获取到pojo对象,进而对数据进行操作。
二、使用注解方式实现IoC
传统的XML配置方式完成IoC,需要配置很多的bean,有一些麻烦,这时候可以使用注解的方式实现自动装配。
第一步:修改数据访问接口实现类UserDAO
package com.lml.dao; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Repository; @Repository public class UserDAO implements IUserDAO{ private static Log log = LogFactory.getLog(IUserDAO.class); public String addUser(String userName) { log.debug("测试:添加图书" + userName + "成功"); return "添加图书" + userName + "成功"; } }
在类上增加了一个注解Repository,在类的开头使用了@Repository注解,它可以被Spring容器识别,启动Spring后,会自动把它转成容器管理的Bean。
Spring提供了3个功能基本和@Component等效的注解,分别对应于用于对DAO,Service,和Controller进行注解。
1:@Repository 用于对DAO实现类进行注解。
2:@Service 用于对业务层注解,但是目前该功能与 @Component 相同。
3:@Constroller用于对控制层注解,但是目前该功能与 @Component 相同。
第二步:修改业务类UserService
package com.lml.service; import javax.annotation.Resource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Service; import com.lml.dao.IUserDAO; @Service public class UserService { private static Log log = LogFactory.getLog(UserService.class); IUserDAO userDAO; public IUserDAO getUserDAO() { return userDAO; } // @Resource装配顺序 // 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常 // 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常 // 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常 // 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配 @Resource //实现注入 public void setUserDAO(IUserDAO userDAO) { this.userDAO = userDAO; } public void storeUser(String userName){ //自动装配。不需要通过配置文件获取bean了 // ApplicationContext ac = new ClassPathXmlApplicationContext("IOCBeans01.xml"); // userDAO = (UserDAO)ac.getBean("userdao"); String result = userDAO.addUser(userName); log.debug("result=" + result); } }
类UserService将对容器管理因为注解了@Service,初始化时会生成一个单例的Bean,类型为UserService。在字段setUserDAO上注解了@Resource,用于注入,Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。
第三步:修改配置文件IOCBeans01.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <!-- <bean id="userdao" class="com.lml.dao.UserDAO"></bean> --> <!-- 启用注解 --> <context:annotation-config /> <context:component-scan base-package="com.lml"></context:component-scan> </beans>
粗体字是新增的xml命名空间与模式约束文件位置。增加了注解扫描的范围,指定了一个包,可以通过属性设置更加精确的范围如:
<context>标记常用属性配置:
resource-pattern:对指定的基包下面的子包进行选取
<context>子标记:
include-filter:指定需要包含的包
exclude-filter:指定需要排除的包
<!-- 自动扫描com.zhangguo.anno.bo中的类进行扫描 -->
<context:component-scan base-package="com.zhangguo.anno" resource-pattern="bo/*.class" />
<context:component-scan base-package="com.zhangguo.anno" >
<context:include-filter type="aspectj“ expression="com.zhangguo.anno.dao.*.*"/>
<context:exclude-filter type=“aspectj” expression=“com.zhangguo.anno.entity.*.*”/>
</context:component-scan>
include-filter表示需要包含的目标类型,exclude-filter表示需要排除的目标类型,type表示采的过滤类型,共有如下5种类型:
| Filter Type | Examples Expression | Description |
| annotation | org.example.SomeAnnotation | 注解了SomeAnnotation的类 |
| assignable | org.example.SomeClass | 所有扩展或者实现SomeClass的类 |
| aspectj | org.example..*Service+ | AspectJ语法表示org.example包下所有包含Service的类及其子类 |
| regex | org\.example\.Default.* | Regelar Expression,正则表达式 |
| custom | org.example.MyTypeFilter | 通过代码过滤,实现org.springframework.core.type.TypeFilter接口 |
expression表示过滤的表达式。
<!-- 1、如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类 -->
<context:component-scan base-package="com.zhangguo.Spring051"
resource-pattern="ioc04/A*.class">
</context:component-scan>
只扫描com.zhangguo.Spring051.ioc04下所有名称以A开始的类。
<!--2、扫描注解了org.springframework.stereotype.Repository的类
exclude-filter表示排除,include-filter表示包含,可以有多个-->
<context:component-scan base-package="com.zhangguo.Spring051.ioc04">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" />
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
<!--3、aspectj类型,扫描dao下所有的类,排除entity下所有的类--> <context:component-scan base-package="com.zhangguo.anno" > <context:include-filter type="aspectj" expression="com.zhangguo.anno.dao.*.*"/> <context:exclude-filter type="aspectj" expression="com.zhangguo.anno.entity.*.*"/> </context:component-scan>
第四步:修改测试类
package com.lml.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lml.service.UserService; public class Test01 { @org.junit.Test public void testStoreUser(){ ApplicationContext ac = new ClassPathXmlApplicationContext("IOCBeans01.xml"); UserService userService = ac.getBean(UserService.class); userService.storeUser("李蒙龙"); } }

浙公网安备 33010602011771号