目录:
jar包下载:
http://repo.spring.io/libs-release-local/org/springframework/spring/
- spring:
- 第三方日志jar包:
- 下载:百度搜索commons-logging.jar mvn,点击第一个链接
-
- 要这个
-
- 下载jar文件:
- 给eclipse下插件,以便编程时得到提示信息
- spring tool suite:
- 下载地址:http://spring.io/tools3/sts/all
- 之后点击eclipse的help中安装
- 也可以直接下载sts工具:https://spring.io/tools(相当于加入了spring的ecplise)
- spring tool suite:
- 导入jar包
- 配置applicationContext.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 产生的对象被放在spring中一个成为ioc容器的地方 --> <bean id="student" class="claire.entity.Student"> <property name="stuNo" value="2"></property> <property name="stuName" value="ls"></property> <property name="stuAge" value="24"></property> </bean> </beans>
package claire.entity; public class Student { private int stuNo; private String stuName; private int stuAge; @Override public String toString() { return this.stuNo + "," + this.stuName + "," + this.stuAge; } public int getStuNo() { return stuNo; } public void setStuNo(int stuNo) { this.stuNo = stuNo; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public int getStuAge() { return stuAge; } public void setStuAge(int stuAge) { this.stuAge = stuAge; } }
package claire.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import claire.entity.Student; public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student bean = (Student)context.getBean("student"); System.out.println(bean); } }
结果:
- *Test.java中的ApplicationContext是应用上下文,它继承自BeanFactory接口,有三个常用实现类:
- ClassPathXmlApplicationContext: 该类从指定类路径中寻找指定xml文件,找到并装载完成ApplicationContext的实例化工作。
- FileSystemApplicationContext: 该类从指定的文件系统中寻找指定xml文件,找到并装载完成ApplicationContext的实例化工作。
- XmlWebApplicationContext: 该类从web应用中寻找指定xml文件,找到并装载完成ApplicationContext的实例化工作。
- 在java项目中通过ClassPathXmlApplicationContext手工实例化ApplicationContext通常为不二选择,但是在web项目中,web项目的启动是由相应的web服务器负责的,因此,在web项目中ApplicationContext容器的实例化工作最好交由web服务器,spring为此提供了:
- 基于ContextLoaderListener实现(在web.xml中加入<context>及<listener>节点并进行相应配置)
- 基于ContextLoaderServlet实现(在web.xml中加入<context>及<servlet>节点并进行相应配置)
package spring_20190115; public class User { private int id; private String name; public User() { System.out.println("创建了一个user对象"); } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
IOC容器底层是利用反射调用无参构造,故而在IOC容器中定义bean的前提是类必须提供无参构造
- 默认是单例:
<?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="user" class="spring_20190115.User"> </bean> </beans>
如此配置等同于
<bean id="user" class="spring_20190115.User" scope="singleton"></bean>
单例模式对于无会话状态的Bean(如DAO,业务逻辑组件)来说,是最理想的选择。
package spring_20190115; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class APP { @Test public void testApp() throws Exception{ ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User)ac.getBean("user"); User user2 = (User)ac.getBean("user"); } }
- 改为多例:
-
<bean id="user" class="spring_20190115.User" scope="prototype"></bean>
- 单例模式下默认在创建容器时救创建所有单例对象,如果希望在第一次访问的时候才创建,可通过设置bean标签的lazy-init="true"实现(只对单例模式有效);多例模式(原型模式)下时访问才会创建对象, Spring不能对一个原型模式Bean的整个生命周期负责,容器在初始化,装配好一个原型模式实例后,就将它交由客户端不再过问,因此,客户端需要负责原型模式实例的生命周期管理 。 。
-
- singleton 单例
1) 创建对象
如果有配置延迟初始化,
lazy-init=true 如果单例的对象有配置延迟初始化, 在创建容器之后,在第一次从容器获取对象的时候
创建单例的对象!
如果没有配置或延迟初始化为默认值, 单例的对象会在创建容器的时候创建对象
2) 执行初始化方法 , init-method配置的方法会执行
3) 调用容器destroy() 方法时候,容器在销毁单例对象的实例的时候,会调用destroy-method对应的方法
此时bean对象会被销毁!
- prototype 多例
1) 每次在从容器获取对象的时候,都会创建新的对象
2) 每次创建完对象后,就执行初始化方法
3) java会回收不用资源(jvm gc)
- 调用无参构造器
- 调用有参构造器(因为不管什么类型都是直接放到双引号中,难以区分,建议配合type/name属性使用)
-
<?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="user" class="spring_20190115.User" lazy-init="true"></bean> <!-- 调用有参构造器--> <bean id="str" class="java.lang.String"> <constructor-arg value="Jack"></constructor-arg> </bean> <bean id="user2" class="spring_20190115.User"> <constructor-arg index="0" type="int" value="1000"></constructor-arg> <!-- ref 当引用的是IOC容器中的对象的时候,使用ref --> <constructor-arg index="1" type="String" ref="str"></constructor-arg> </bean> </beans>
package spring_20190115; public class User { private int id; private String name; public User() { System.out.println("无参构造器"); } public User(String name) { // super(); System.out.println("一个参数构造器"); this.name = name; } public User(int id, String name) { System.out.println("两个参数构造器"); this.id = id; this.name = name; } @Override public String toString() { // TODO Auto-generated method stub return this.name+"---"+this.id; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package spring_20190115; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class APP { @Test public void testApp() throws Exception{ ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //无参构造 User user = (User)ac.getBean("user"); System.out.println(user); User user2 = (User) ac.getBean("user2"); System.out.println(user2); //有参构造 User user3 = (User) ac.getBean("user3"); System.out.println(user3); } }
-
- 工厂方法
- 静态方法
- 非静态方法
-
package spring_20190115; /** * 创建user对象工厂 * @author claire * */ public class UserFactory { /** * 非静态工厂方法 * @return user对象 */ public User getInstance(){ return new User(100, "工厂非静态方法,创建对象"); } /** * 静态工厂方法 * @return */ public static User getStaticInstance(){ return new User(100, "工厂静态方法,创建对象"); } }
<?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="user" class="spring_20190115.UserFactory" factory-method="getStaticInstance"> </bean> <!-- 非静态方法创建对象 --> <bean id="factory" class="spring_20190115.UserFactory"></bean> <bean id="user2" factory-bean="factory" factory-method="getInstance"></bean> </beans>
- 反射
即给对象的属性赋值的方式:
- 构造函数赋值
- 自动装配(见下只适用于引用类型ref)
- 注解实现自动装配
- p名称空间(Spring 3.0以后的特性): xmlns:p="http://www.springframework.org/schema/p"
<!--方式三: p名称空间 --> <bean id="str" class="java.lang.String"> <constructor-arg value="Summer"></constructor-arg> </bean> <bean id="user" class="spring_20190115.User" p:id="1000" p:name-ref="str"> </bean>
- set方式注入
- 普通字段赋值
<!-- set方式注入属性值--> <bean id="user" class="spring_20190115.User"> <property name="id" value="1000"></property> </bean>
-
集合属性 (list/map/property)
<!-- list集合属性赋值 --> <property name="list"> <list> <value>happy, summer, sunshine</value> <value>flower</value> </list> </property>
<property name="map"> <map> <entry key="1" value="name"></entry> </map> </property>
<property name="props"> <props> <prop key="cn">China</prop> <prop key="usa">America</prop> </props> </property>
- 普通字段赋值
* 特殊符号注入问题:
使用实体引用(<表示"<", &表示"&" )或者用<![CDATA[]]>标记,进行原样输出。
* 给对象赋值null: <property name="name"><null/></property>
案例:
Dao/service/action实例,处理依赖关系
-
package claire.di; public class UserDao { //模拟保存对象 public void save(){ System.out.println("UserDao.save()"); } }
package claire.di; public class UserService { //创建dao对象:单例,启动创建 //接收IOC容器注入 private UserDao userDao; public void save(){ userDao.save(); } public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
package claire.di; public class UserAction { private UserService userService; public String execute() { userService.save(); return "success"; } public UserService getUserService() { return userService; } // 接收IOC容器注入 public void setUserService(UserService userService) { this.userService = userService; } }
package claire.di; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class APP { private ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml", APP.class); @Test public void testApp() throws Exception{ //从容器中获取action实例 UserAction userAction = (UserAction) ac.getBean("userAction"); //执行方法 userAction.execute(); } }
-
- 属性注入
- 方式一:通过set方法注入,最为常用
<!-- 方式一:通过set方法注入,最为常用 --> <bean id="userDao" class="claire.di.UserDao"></bean> <bean id="userService" class="claire.di.UserService"> <property name="userDao" ref="userDao"></property> </bean> <bean id="userAction" class="claire.di.UserAction" scope="prototype"> <property name="userService" ref="userService"></property> </bean>
- 方式二:内部bean
<!-- 更为紧凑,当创建的对象不被其他地方引用时可以这样写,这样写不通用,内部对象只能用一次 --> <bean id="userAction" class="claire.di.UserAction" scope="prototype"> <property name="userService"> <bean class="claire.di.UserService"> <property name="userDao"> <bean class="claire.di.UserDao"></bean> </property> </bean> </property> </bean>
- 方式三: p名称空间在<beans>标签内部加入 xmlns:p="http://www.springframework.org/schema/p"
<bean id="userDao" class="claire.di.UserDao"></bean> <bean id="userService" class="claire.di.UserService" p:userDao-ref="userDao"></bean> <bean id="userAction" class="claire.di.UserAction" p:userService-ref="userService"></bean>
- 方式一:通过set方法注入,最为常用
- 属性注入
-
-
- 方式四:自动装配(简化配置,但是维护困难,不推荐使用)自动寻找IOC其他bean的id/type
- 方式一:配置到全局:
<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" default-autowire="byName" <!-- 也可以直接在此处加入default-autowire="byName" 配置到全局--> ></beans>
- 方式二:配置到bean节点
<!-- 自动装配 --> <bean id="userDao" class="claire.di.UserDao"></bean> <!-- byName:根据类中的set方法名(去掉"set"子字符串后),查找容器内是否有同名对象 --> <bean id="userService" class="claire.di.UserService" autowire="byName"></bean> <!-- byType:根据类中set方法参数的类型到容器中查找相同类型对象 --> <!-- byType:使用byType时要保证容器内只有唯一一个对应类型,否则会报NoUniqueBeanDefinitionExpection --> <bean id="userAction" class="claire.di.UserAction" autowire="byType"></bean>
- 方式一:配置到全局:
- 方式四:自动装配(简化配置,但是维护困难,不推荐使用)自动寻找IOC其他bean的id/type
-
-
-
- 方式五:注解
-
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <!-- 注解方式实现Spring IOC容器配置 --> <!-- 开启注解扫描 --> <context:component-scan base-package="claire.di"></context:component-scan> </beans>
package claire.di; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; //第一种方式 //等于<bean id="userDao" class="..."></bean> //@Component("userDao") //第二种方式 //@Repository("userDao") //第三种方式: 省略名称,默认是类名,第一个字母小写,即userDao @Repository public class UserDao { //模拟保存对象 public void save(){ System.out.println("UserDao.save()"); } }
package claire.di; import javax.annotation.Resource; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; //@Component("userService") //将当前类加入ioc容器 //@Service("userService") @Service public class UserService { @Resource //会默认根据这个属性的名称去容器找,如果找不到,会根据类型找,再没找到即报错。 private UserDao userDao; public void save(){ userDao.save(); } }
package claire.di; import javax.annotation.Resource; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; //@Component("userAction") //@Controller("userAction") @Controller @Scope("prototype") public class UserAction { @Resource(name = "userService") //这么写需要set方法 private UserService userService; public String execute() { userService.save(); return "success"; } public void setUserService(UserService userService) { this.userService = userService; } }
package claire.di; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import spring_20190115.User; public class APP { private ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml", APP.class); @Test public void testApp() throws Exception{ //从容器中获取action实例 UserAction userAction = (UserAction) ac.getBean("userAction"); //执行方法 userAction.execute(); } }
-
注解总结:简化配置,不利于后期维护,如果修改对象创建、关系处理,需要改代码!
-
@Component 表示一个组件(类),把当前组件加入ioc容器。加入容器的组件的名称默认是类名第一个字母小写
-
@Component(“”) 指定加入ioc容器的组件类的类名,可细化位:
-
@Repository 标识是一个持久层的组件(dao层注解)
-
@Service 标识是一个业务逻辑层的组件(service层注解)
-
@Controller 标识是一个控制层的组件
-
-
@Scope("prototype") 指定对象单例/多例
-
@Resource 1. 默认根据修饰的字段名称会取ioc容器找对象自动注入。找到后注入
2. 如果名称没有找到,再根据类型查找 找到后就立刻注入。 如果改类型在ioc容器中有多个对象,报错!
3. 根据类型也没有找到对象,报错!
-
@Resource(name =””) 会根据指定的名称去容器找对象自动注入
- @Autowired: 作用相当于@Resource,不同在于Autowired默认按照bean的类型进行装配,而Resource默认按照bean实例名称进行装配。
-
-
- 方式五:注解
-
把action的创建,交给spring的ioc容器。
额外引入jar文件:
spring-web-4.3.9.RELEASE.jar 【spring源码】
struts2-spring-plugin-2.5.14.1.jar 【struts源码】
整合完整步骤:
1. 引入jar
Struts核心jar
Spring Core 核心 (5个)
Web 对web支持 (2个)
2. 配置
-
- applicationContext.xml
<bean id="userAction" class="claire.web.action.UserAction"></bean>
- struts.xml:
- <!-- 在action配置中,class属性直接引用spring容器中的对象 -->
<action name="user" class="userAction"> <result>/index.jsp</result> </action>
- <!-- 在action配置中,class属性直接引用spring容器中的对象 -->
- web.xml
- struts2核心过滤器
<!-- 配置structs2的全局过滤器 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 启动时候,配置加载springIOC容器(在index.html中ctrl+F搜索convenient ApplicationContext即可,但是记得更改路径加入classes如下)
<!-- 配置spring --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
- struts2核心过滤器
- applicationContext.xml