Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
Spring是2003年兴起的一个轻量级的java框架, 由 Rod Johnson 在其编著的《Expert one on one J2EE design and development》一书中阐述的思想和理念衍生而来。
Spring 有两个核心 IOC
& aop
IOC
IOC 的全称是 Inversion Of Control 翻译过来是控制反转的意思。 把对象的创建工作交给框架来完成
UserService userService = new UserServiceImpl(); ---> 问框架要对象
AOP
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
从早期的直接new具体类 ---> 面向接口编程
面向接口编程 --使用工厂
使用Spring来替代
导入jar包
beans
| code
| context
| expression
4个日志jar包 , log4j.properties
编写业务逻辑类
public interface UserService { void save(); } public class UserServiceImpl implements UserService { @Override public void save(){ System.out.println("调用了UserServiceImpl的save方法~!~!"); } }
ml托管业务逻辑类
在src下,创建一个xml, 名字随意。 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"> <bean id="us" class="com.pri.service.impl.UserServiceImpl"></bean> </beans>
创建工厂,问工厂要对象
public class MainTest { @Test public void testSave(){ /* UserService userService = new UserServiceImpl(); userService.save();*/ //1. 创建工厂 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //2. 问工厂要实例对象 UserService userService =(UserService) context.getBean("us"); //3. 调用方法 userService.save(); } }
xml解释
<!-- bean 标签是用来告诉spring,需要帮忙创建什么类的实例 id | name : 标识符 , 以后拿着id的值就能问spring要对应类的实例。 class : 托管类的全路径 scope: 用于表示生成的实例模式 spring默认生成的实例是单例。 scope="prototype" 表示生成多例 init-method: 生成实例之后,调用的方法 destroy-method: 销毁实例的时候调用的方法 --> <bean id="us" class="com.pri.service.impl.UserServiceImpl" scope="prototype" init-method="init" destroy-method="destroy"> </bean>
代码解释
public class MainTest { @Test public void testSave(){ /* UserService userService = new UserServiceImpl(); userService.save();*/ //1. 创建工厂 , 需要告诉工厂,xml文件在哪里。 不会这么写 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //2. 问工厂要实例对象 , 可以让工厂送过来 UserService userService =(UserService) context.getBean("us"); //3. 调用方法 userService.save(); //关闭工厂 以后一般不关闭工厂 ((AbstractApplicationContext) context).close(); } }
把对象交给spring创建的方式
要求托管类的务必提供无参构造方法,当然以后可以配置让spring走有参构造
代码
public class UserServiceImpl implements UserService { //spring创建实例, 要求托管类默认提供无参构造方法。 @Override public void save(){ System.out.println("调用了UserServiceImpl的save方法~!~!"); } }
配置
<?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="us" class="com.pri.service.impl.UserServiceImpl"></bean> </beans>
要求提供工厂类,并且工厂的方法是静态方法, 在方法里面生成业务逻辑类的实例
代码
public class StaticFactory { public static UserService getBean(){ System.out.println("要创建UserServiceImpl的实例了~~"); return new UserServiceImpl(); } }
xml
<!-- 我们也是拿着us去问spring工厂要实例, 它直接就调用了StaticFactory的getBean方法拿到实例,然后返回 --> <!-- 静态工厂配置 --> <bean id="us" class="com.pri.factory.StaticFactory" factory-method="getBean"></bean>
代码
public class InstanceFactory { public UserService getBean(){ System.out.println("要创建UserServiceImpl的实例了~~"); return new UserServiceImpl(); } }
xml
<bean id="factory" class="com.pri.factory.InstanceFactory"/> <bean id="us" factory-bean="factory" factory-method="getBean"></bean>
后面的两种工厂的配置,开发当中几乎不会用。
什么是依赖注入?
DI : 全称是 dependency Injection 翻译过来是依赖注入 本意是在实例化对象的时候,对它里面的成员属性进行值的注入。
public class UserServiceImpl{ private String name; //1. set方法 public void setName(String name){ this.name=name; } } UserServiceImpl us = new UserServiceImpl(); us.setName("zhangsan"); //现在实例的创建是工厂来完成,我们想让工厂创建实例的时候,顺便把成员变量给赋值了。
给成员变量赋值的方式【DI的方式】
①set方法
②有参构造
注入的方式有两种: 有参构造 | set方法
提供有参构造方法
代码
public class UserServiceImpl implements UserService { private String address; public UserServiceImpl(String address) { super(); this.address = address; } @Override public void save(){ System.out.println("调用了UserServiceImpl的save方法~!~!=="+address); } }
xml
<bean id="us" class="com.pri.service.impl.UserServiceImpl" > <!-- 指定构造的参数, name: 参数的名称, values: 参数的值 --> <constructor-arg name="address" value="深圳"/> </bean>
代码
public class UserServiceImpl implements UserService { private String address; public void setAddress(String address) { this.address = address; } @Override public void save(){ System.out.println("调用了UserServiceImpl的save方法~!~!=="+address); } }
xml
<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="us" class="com.pri.service.impl.UserServiceImpl" > <property name="address" value="宝安"/> </bean> </beans>
代码
public class UserServiceImpl implements UserService{ private String [] address; public void setAddress(String [] address) { this.address = address; } ... }
xml
<property name="address" > <array> <value>北京1</value> <value>北京2</value> <value>我爱北京天安门,天安门很大</value> </array> </property>
代码
public class UserServiceImpl implements UserService{ private List<String> address; public void setAddress(List<String> address) { this.address = address; } ... }
xml
<property name="address"> <list> <value>北京1</value> <value>北京2</value> <value>我爱北京天安门,天安门很大</value> </list> </property>
代码
public class UserServiceImpl implements UserService{ private Map<String ,Object> address; public void setAddress( Map<String ,Object> address) { this.address = address; } ... }
xml
<property name="address"> <map> <entry key="地址1" value="北京1"/> <entry key="地址2" value="北京2"/> <entry key="地址3" value="北京3"/> </map> </property>
代码
public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save(){ System.out.println(" ==调用了UserServiceImpl的save方法~!~!=="); /*UserDao userDao =new UserDaoImpl(); //创建对象 ---》 IOC ----> bean标签 userDao.save();*/ //1. 我们自己创建对象,然后自己用。 //2. 工厂创建对象,我们去问它要对象 //3. 工厂创建对象,让工厂自己送过来对象。 --- 》 注入对象 userDao.save(); } }
xml
<!-- 让spring创建UserServiceImpl的实例 --> <bean id="us" class="com.pri.service.impl.UserServiceImpl" > <!-- 让spring调用UserServiceImpl的setUserDao的方法,并且把刚才创建好的ud的那个实例当成参数,传递进去。 这就完成了对象的注入 --> <property name="userDao" ref="ud"></property> </bean> <!-- 让spring创建UserDaoImpl的实例 --> <bean id="ud" class="com.pri.dao.impl.UserDaoImpl"></bean>
依赖注入的方式已经固定化了,就是 有参构造 | set方法。 但是spring担心程序员在xml的配置要写的代码很多,然后程序员就不喜欢用了。所以spring针对xml的注入,提出了两种简化写法 : p 名称空间 | c名称空间
p 名称空间
针对的是这个
<property name="" />
, 也就表明了代码里面声明注入的方式是 set方式
<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="us" class="com.pri.service.impl.UserServiceImpl" p:address="北京"> </bean>
c 名称空间
针对的是这个
<constructor-arg/>
, 也就要求我们的代码声明注入的方式必须是有参构造
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="us" class="com.pri.service.impl.UserServiceImpl" c:address="北京"> </bean>
SPEL 属性注入
可以完成逻辑运算
<bean id="us" class="com.pri.service.impl.UserServiceImpl" > <property name="address" value="#{1>2}"/> </bean>
在servlet里面创建工厂、然后获取实例对象
public class ServletDemo extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("调用了get方法~~~"); ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService us = (UserService)context.getBean("us"); us.save(); ((AbstractApplicationContext) context).close(); } }
2个问题
1. 每次请求过来都会解析xml, 创建工厂。如果xml内容很多,就比较的耗时。
解决方法:
工具类 | 静态代码块
2. 工厂创建的时机有点晚。 第一次使用的时候才会创建。
解决方法:
提前创建 --- 提前到项目发布 --- 项目发布之后,就会创建一个类的实例(ServletContext)-----ServletContextListner
a. 如果是我们自己处理的, 定义监听器, 然后在监听器里面创建工厂 , 存储工厂到一个地方去,以便所有的servlet都能使用到工厂。 servletContext.
b. 监听器不用你们写了,工厂创建的代码不用你们写了。放到servletcontext也不用写了。 配置监听器。
把上面出现的问题给解决掉 ,必须要导入额外的jar包
spring-web-xxx.jar
只要项目一发布,就立即创建工厂,那么我们必须的抓住项目发布的这个契机。 以前在servlet阶段,学过一种东西监听器 ,可以监听作用域对象的创建与销毁 , SerlvetContext, 这是最大的作用域,全局只有一个对象。
在web.xml 中配置 监听器 并且配置param 指定spring配置文件所在
<!-- 配置listener,目的就是让项目发布的回收,能够创建工厂。但是创建工厂 需要解析xml文件,它默认回到/WEB-INF/applicationContext.xml 要是找不到就报错,除非我们告诉它,xml文件在哪里 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 告诉listener, 配置文件在哪里 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
通过工具类获取之前创建好的工厂
public class ServletDemo extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("调用了get方法~~~"); //ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); UserService us = (UserService)context.getBean("us"); us.save(); //((AbstractApplicationContext) context).close(); } ... }
如对本文有疑问, 点击进行留言回复!!
[JVM学习之路]一、初识JVM,了解其结构、模型及生命周期
【JAVA并发编程】LinkedBlockingQueue原理
网友评论