spring
1 Spring 定义:
简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
分层:1 web, 2 service 3 dao
2 sping 的特点
①、方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
②、AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
③、声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
④、方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
⑤、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
⑥、降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
3 Spring 组成
spring主要包括三个部分
1 IoC(Inversion of Control,控制反转)。这是spring的核心,贯穿始终, 将对象的创建权交由spring完成
2 aop 面向切面
3 Di 依赖注入 为类的属性设置相关的值
4 spring创建对象的三种方式
(1)在创建对象前应该先导入相应的夹包,核心夹包如下:
spring夹包
spring-beans-5.0.0.RELEASE.jar
spring-core-5.0.0.RELEASE.jar
spring-context-5.0.0.RELEASE.jar
pring-expression-5.0.0.RELEASE.jar
日志需要的夹包
commons-logging-1.2.jar
log4j-1.2.16.jar
spring 中bean 标签的属性详情:
(1)、id:Bean的唯一标识名。它必须是合法的XMLID,在整个XML文档中唯一。
(2)、name:用来为id创建一个或多个别名。它可以是任意的字母符合。多个别名之间用逗号或空格分开。
(3)、class:用来定义类的全限定名(包名+类名)。只有子类Bean不用定义该属性。
(4)、parent:子类Bean定义它所引用它的父类Bean。这时前面的class属性失效。子类Bean会继承父类Bean的所有属性,子类Bean也可以覆盖父类Bean的属性。注意:子类Bean和父类Bean是同一个Java类。
(5)、abstract(默认为”false”):用来定义Bean是否为抽象Bean。它表示这个Bean将不会被实例化,一般用于父类Bean,因为父类Bean主要是供子类Bean继承使用。
(6)、singleton(默认为“true”):定义Bean是否是Singleton(单例)。如果设为“true”,则在BeanFactory作用范围内,只维护此Bean的一个实例。如果设为“flase”,Bean将是Prototype(原型)状态,BeanFactory将为每次Bean请求创建一个新的Bean实例。
(7)、lazy-init(默认为“default”):用来定义这个Bean是否实现懒初始化。如果为“true”,它将在BeanFactory启动时初始化所有的SingletonBean。反之,如果为“false”,它只在Bean请求时才开始创建SingletonBean。
(8)、autowire(自动装配,默认为“default”):它定义了Bean的自动装载方式。
1、“no”:不使用自动装配功能。
2、“byName”:通过Bean的属性名实现自动装配。
3、“byType”:通过Bean的类型实现自动装配。
4、“constructor”:类似于byType,但它是用于构造函数的参数的自动组装。
5、“autodetect”:通过Bean类的反省机制(introspection)决定是使用“constructor” 还是使用“byType”
(9)、depends-on(依赖对象):这个Bean在初始化时依赖的对象,这个对象会在这个Bean初始化之前创建。
(10)、init-method:用来定义Bean的初始化方法,它会在Bean组装之后调用。它必须是一个无参数的方法。
(11)、destroy-method:用来定义Bean的销毁方法,它在BeanFactory关闭时调用。同样,它也必须是一个无参数的方法。它只能应用于singletonBean。
(12)、factory-method:定义创建该Bean对象的工厂方法。它用于下面的“factory-bean”,表示这个Bean是通过工厂方法创建。此时,“class”属性失效。
(13)、factory-bean:定义创建该Bean对象的工厂类。如果使用了“factory-bean”则“class”属性失效。
(14) scope(singleton 单例 ,prototype 多例)
单例 只有一个该类的对象
多例 有很多该类的对象,每次都是一个新对象。
方式一:利用默认的构造方法
在 src 目录下新建 spring.xml 文件,这是 spring 配置文件,添加如下代码:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.rl.entity.User" scope="prototype"> </bean> </beans>
测试:
public static void main(String[] args) { // TODO Auto-generated method stub ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("spring.xml");//加载配置文件 配置文件为默认为src下 User user=(User)app.getBean("user"); System.out.println(user); }
方式二 利用静态工厂方法
(1)首先创建静态工厂如下
package com.rl.entity; public class UserFactory { public static User getUser(){ return new User(); } }
(2) 配置好配置文件
factory-method 工厂中返回对象的方法名
class 工厂的类的全路径
<bean id="userFactory" factory-method="getUser" class="com.rl.entity.UserFactory"></bean>
(3) 测试
ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("spring.xml"); User user=(User)app.getBean("userFactory"); System.out.println(user);
方式三 利用实例工厂方法
(1) 创建类 并创建要返回对象的方法
public class HelloInstanceFactory { //利用实例工厂方法创建对象 public HelloIoc getInstance(){ HelloIoc instanceIoc = new HelloIoc(); return instanceIoc; } }
(2)配置 配置文件
factory-bean:指定当前Spring中包含工厂方法的beanID
factory-method:工厂方法名称
<bean id=
"instanceFactory"
class
=
"com.ys.ioc.HelloInstanceFactory"
></bean>
<bean id=
"instance"
factory-bean=
"instanceFactory"
factory-method=
"getInstance"
></bean>
(3)测试
ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("spring.xml"); User user=(User)app.getBean("instance"); System.out.println(user);
5 属性注入
属性注入分为两种方式(构造器方式注入,Setter注入)
1 构造器
index 构造器中第几个参数 (从0开始)
name 构造器参数名
value 构造器参数值
<bean id="user" class="com.rl.entity.User" scope="prototype"> <constructor-arg index="" name="" value=""></constructor-arg> </bean>
2 Setter 方式
name 属性名 value 属性值 ref 注入对象(对象也需要在bean中实例化)
<property name="" value="" ></property>
<property name="" ref=""></property>
6 Map、Set、List、数组、属性集合的注入方法配置文件
原始的类:
public class Department { private String name; private String [] empName;//数组 private List<Employee> empList;//list集合 private Set<Employee> empsets;//set集合 private Map<String,Employee> empMaps;//map集合 private Properties pp;//Properties的使用
}
在配置文件中的配置如下:
<bean id="department" class="com.hsp.collection.Department"> <property name="name" value="财务部"/> <!-- 给数组注入值 --> <property name="empName"> <list> <value>小明</value> <value>小明小明</value> <value>小明小明小明小明</value> </list> </property> <!-- 给list注入值 list 中可以有相当的对象 --> <property name="empList"> <list> <ref bean="emp2" /> <ref bean="emp1"/> <ref bean="emp1"/> <ref bean="emp1"/> <ref bean="emp1"/> <ref bean="emp1"/> <ref bean="emp1"/> </list> </property> <!-- 给set注入值 set不能有相同的对象 --> <property name="empsets"> <set> <ref bean="emp1" /> <ref bean="emp2"/> <ref bean="emp2"/> <ref bean="emp2"/> <ref bean="emp2"/> </set> </property> <!-- 给map注入值 map只有key不一样,就可以装配value --> <property name="empMaps"> <map> <entry key="11" value-ref="emp1" /> <entry key="22" value-ref="emp2"/> <entry key="22" value-ref="emp1"/> </map> </property> <!-- 给属性集合配置 --> <property name="pp"> <props> <prop key="pp1">abcd</prop> <prop key="pp2">hello</prop> </props> </property> </bean> <bean id="emp1" class="com.hsp.collection.Employee"> <property name="name" value="北京"/> <property name="id" value="1"/> </bean> <bean id="emp2" class="com.hsp.collection.Employee"> <property name="name" value="天津"/> <property name="id" value="2"/> </bean>
取值:
ApplicationContext ac=new ClassPathXmlApplicationContext("com/lc/collection/beans.xml"); Department department=(Department) ac.getBean("department"); System.out.println(department.getName()); for(String emName:department.getEmpName()){ System.out.println(emName); } /* * 通过list集合取出数据 */ System.out.println("**********通过list集合取出数据*****"); for(Employee e : department.getEmpList()){ System.out.println("name="+e.getName()+" "+e.getId()); } /* * 通过set集合取出数据 */ System.out.println("**********通过set集合取出数据*****"); for(Employee e : department.getEmpsets()){ System.out.println("name="+e.getName()); } /* * 通过map集合取出数据 迭代器 */ System.out.println("*******通过map集合取出数据 迭代器****"); //1.迭代器 Map<String,Employee> empmaps=department.getEmpMaps(); Iterator it=empmaps.keySet().iterator(); while(it.hasNext()){ String key=(String) it.next(); Employee emp=empmaps.get(key); System.out.println("key="+key+" "+emp.getName()); } System.out.println("*******通过map集合取出数据 简洁方法****"); //2.简洁方法 for(Entry<String,Employee> entry1:department.getEmpMaps().entrySet()){ System.out.println(entry1.getKey()+" "+entry1.getValue().getName()); }
7 注解方式配置bean
使用注解方式配置的时候必须要配置自动扫描的包 在测试的时候一定要用注解注明改类
@Service 服务层
@Repository 数据访问层
@Controller 控制层
@Component 不清楚在哪一层
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 自动扫描该包,使 SpringMVC 为包下用了@controller注解的类是控制器 --> <context:component-scan base-package="com.rl.entity" /> <context:component-scan base-package="com.weixiao.listener" /> <bean id="userFactory" factory-method="getUser" class="com.rl.entity.UserFactory"></bean> </beans>
@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。如下:
public class TestServiceImpl { @Autowired @Qualifier("userDao") private UserDao userDao; }
(2)@Resource
@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
public class TestServiceImpl { // 下面两种@Resource只要使用一种即可 @Resource(name="userDao") private UserDao userDao; // 用于字段上 @Resource(name="userDao") public void setUserDao(UserDao userDao) { // 用于属性的setter方法上 this.userDao = userDao; } }