文章目录
Spring入门
一、Spring概论
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
在Javaweb中,我们需要自己手动new大量的对象,**但是在spring框架中,这些new对象的操作可以由spring完成,**大大减少了程序员的工作量,以及减少后期代码维护的成本
并且在spring框架中,我们只需要修改配置文件即可完成代码的修改,不需要对java代码进行更改,便于维护代码
二、Spring开发步骤
上图就是Spring框架创建对象的过程
- 首先在Spring的xml配置文件中,用一个Bean容器给其一个id(id不可重复)
- 在程序中只需要使用Spring客户端的getBean(id标识)方法即可
- 而Spring框架会读取xml配置文件,根据id表示获得Bean全限定名,接着通过反射创建Bean对象,最后返回对象
Spring的开发步骤:
首先导入Spring开发的基本包坐标
<!--导入springjar包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
编写Dao接口和实现类
接着创建Spring核心配置文件(在resources右键——>新建——>XML配置文件——>Spring配置)
在Spring配置文件中配置UserDaoImpl
<?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="userDao" class="com.kang.impl.UserDaolmpl" ></bean> </beans>
在Spring的API获取到Bean实例
package com.kang.demo; import com.kang.UserDao; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserDaoDemo { public static void main(String[] args) { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) app.getBean("userDao"); userDao.save(); } }
- 在Spring的XML配置文件中,class的路径必须为全限名字,例如com.kang.impl.UserDaolmpl
三、 Spring配置文件
1、Bean标签范围配置
scope:指的是对象的作用范围,其取值如下
取值范围 | 说明 |
---|---|
singleton | 默认值,单例的 |
prototype | 多例的 |
request | WEB项目中,Spring创建的一个Bean的对象,将对象存入到request域中 |
session | WEB项目中,Spring创建的一个Bean的对象,将对象存入到session域中 |
golobal sesssion | WEB项目中,应用在Portlet环境,如果没有Portlet环境那么golobal sesssion香港党羽seesion |
-
当scope取值为singleton的时候
<?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="userDao" class="com.kang.impl.UserDaolmpl" scope="singleton"></bean> </beans>
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
package com.kang.test; import com.kang.UserDao; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { @Test public void test01(){ //当程序执行完这条代码,也就是读取完xml配置文件,对象就被创建,而且多次创建的对象都是同一个对象 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao1 = (UserDao) app.getBean("userDao"); UserDao userDao2 = (UserDao) app.getBean("userDao"); System.out.println(userDao1); System.out.println(userDao2); } }
Bean的生命周期:
- 对象创建:当应用加载,创建容器时,对象就被创建
- 对象运行:只要容器在,对象一直活着
- 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
-
当scope取值为prototype的时候
<?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="userDao" class="com.kang.impl.UserDaolmpl" scope="prototype"></bean> </beans>
Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时,实例化Bean
package com.kang.test; import com.kang.UserDao; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { @Test public void test01(){ ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //当程序执行完这条代码,也就是读取完xml配置文件,对象就被创建,而且多次创建的对象为不同个对象 UserDao userDao1 = (UserDao) app.getBean("userDao"); UserDao userDao2 = (UserDao) app.getBean("userDao"); System.out.println(userDao1); System.out.println(userDao2); } }
Bean的生命周期:
- 对象创建:当使用对象时,创建新的对象实例
- 对象运行:只要对象在使用中,就一直活着
- 对象销毁:对象长时间不使用,就会被JAVA的垃圾回收器回收了
2、Bean实例化三种方式
Bean实例化的三种方式:
- 无参构造方法实例化
- 工厂静态方法实例化
- 工厂实例方法实例化
2.1、无参构造方法实例化
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
上述测试代码中所有的Bean实例化均为无参构造方法
2.2、工厂静态方法实例化
public class UserDaolmplFactory {
public static UserDaolmpl CreateUserDao(){
return new UserDaolmpl();
}
}
<bean id="userDao" class="com.kang.factory.UserDaolmplFactory" factory-method="CreateUserDao"></bean>
只需要在xml文件中,用factory-method告诉spring框架这是一个工厂模式并且工程的方法是CreateUserDao,那么spring框架仍然会返回一个Bean的实例化
spring框架会先找到com.kang.factory.UserDaolmplFactory,然后调用CreateUserDao这个静态方法,即可返回一个UserDao对象
并且java代码不需要有任何修改
2.3、工厂实例方法实例化
在工厂静态方法实例化的实现中,由于工厂里的方法是静态的,所以不需要创建工厂实例化对象,但是在如果工厂创建对象的方法不是静态的,那应该怎么办?
<bean id="factory" class="com.kang.factory.UserDaolmplFactory"></bean>
<bean id="userDao" factory-bean="factory" factory-method="CreateUserDao"></bean>
- 首先先创建id为factory的bean,让它返回一个工厂的对象
- 然后创建一个id为userDao的bean,在当中指明factory-bean(工厂的bean)的id,然后还有工厂创建对象的方法
- 同样,Java代码不需要修改
3、Bean生命周期配置
Bean可以由程序猿指定初始化和销毁的方法,只需要在xml配置文件的对应bean中加入以下标签
- init-method:指定类中的初始化方法名称
- destroy-method:指定类中的销毁方法名称
<bean id="userDao" class="com.kang.impl.UserDaolmpl" init-method="init" destroy-method="destroy"></bean>
package com.kang.impl;
import com.kang.UserDao;
public class UserDaolmpl implements UserDao {
public UserDaolmpl(){
System.out.println("创建对象");
}
@Override
public void save() {
System.out.println("save running......");
}
//初始化方法
public void init(){
System.out.println("初始化。。。。");
}
//销毁方法
public void destroy(){
System.out.println("销毁.....");
}
}
测试代码
public class SpringTest {
@Test
public void test01(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao");
System.out.println(userDao1);
((ClassPathXmlApplicationContext)app).close();
}
}
4、依赖注入
问题引入:
- 创建 UserService,UserService 内部在调用 UserDao的save() 方法
public class UserServiceImpl implements UserService { @Override public void save() { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) app.getBean("userDao"); userDao.save(); } }
将 UserServiceImpl 的创建权交给 Spring
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean> <bean id="userService" class="com.kang.impl.UserServiceImpl"></bean>
从 Spring 容器中获得 UserService 进行操作
@Test public void test02(){ ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) app.getBean("userService"); userService.save(); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gT469oAN-1645704192217)(Spring入门.assets/image-20220224093008916.png)]
上述做法是将UserService实例和UserDao都存在spring容器中,然后再容器外部获取UserService实例和UserDao实例,然后在程序中进行结合
这当中存在的问题是:加载配置文件的时候,不需要getBean方法,配置文件的内容都被执行了,导致配置文件加载了多次,浪费资源
在test中,只需要UserService,但是UserDao也实例化了
因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在 Spring容器中,将UserDao设置到UserService内部。
要解决这个问题,就需要用到依赖引入
4.1、依赖引入的方式
通过构造方法和set方法实现将UserDao注入到UserService内部
4.1.1、set方法注入
set方法注入的前提,是要在UserServiceImpl里定义一个私有变量UserDao
然后通过set方法给该私有变量赋值
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Override
public void save() {
userDao.save();
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<!--第一个userDao是指set方法后面的UserDao, 既setUserDao-->
<!--第二个userDao 是指上面的id的userDao的Bean实例化返回的UserDao对象-->
<property name="userDao" ref="userDao"/>
</bean>
注意:虽然两个userDao写法一样,但是两个userDao所代表的意思并不一样,注意区分
set方法注入还可以用P空间命名注入
首先引入P空间命名空间:
xmlns:p="http://www.springframework.org/schema/p"
接着,修改注入方式:
<bean id="userService" class="com.kang.impl.UserServiceImpl" p:userDao-ref="userDao"> <!--第一个userDao是指set方法后面的UserDao(首字母大写换小写), 既setUserDao--> <!--第二个userDao 是指上面的id的userDao(对象引用)--> <!--<property name="userDao" ref="userDao"/>--> </bean>
spring的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="factory" class="com.kang.factory.UserDaolmplFactory"></bean>-->
<!--<bean id="userDao" factory-bean="factory" factory-method="CreateUserDao"></bean>-->
<!--<bean id="userDao" class="com.kang.impl.UserDaolmpl" init-method="init" destroy-method="destroy"></bean>-->
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl" p:userDao-ref="userDao">
<!--第一个userDao是指set方法后面的UserDao, 既setUserDao-->
<!--第二个userDao 是指上面的id的userDao-->
<!--<property name="userDao" ref="userDao"/>-->
</bean>
</beans>
4.1.2、通过构造方法注入
创建有参构造方法
package com.kang.impl;
import com.kang.dao.UserDao;
import com.kang.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName UserServiceImpl
* @Description TODO
* @Author kang
* @Date 2022/2/24 上午 9:22
* @Version 1.0
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public UserServiceImpl() {
}
@Override
public void save() {
userDao.save();
}
}
配置spring的xml配置文件
<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl" >
<!--第一个userDao是指有参构造方法的参数-->
<!--第二个userDao是指引用对象,即上面的id属性-->
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
Java的测试类代码依然不用变
5、Bean的依赖注入的数据类型
Bean的依赖注入的数据类型有很多种,除了上面的对象还支持普通数据类型,集合等可以在容器中进行注入
注入的三种基本数据类型
- 普通数据类型
- 引用数据类型
- 集合数据类型
上述对对象的操作就是对引用数据类型的依赖注入
5.1、普通数据类型的注入
public class UserServiceImpl implements UserService {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void save() {
System.out.println("name = " + name);
System.out.println("age = " + age);
}
}
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="name" value="小明"></property>
<property name="age" value="18"></property>
</bean>
注意:ref 和 value的使用场景不一样
- ref:对象引用
- value:普通数据
5.2、集合数据类型(List< String >)的注入
package com.kang.impl;
import com.kang.dao.UserDao;
import com.kang.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class UserServiceImpl implements UserService {
List<String> list;
public void setList(List<String> list) {
this.list = list;
}
@Override
public void save() {
System.out.println(list);
}
}
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<list>
<value>华为</value>
<value>小米</value>
<value>苹果</value>
</list>
</property>
</bean>
上述是集合中为普通数据类型的案例
5.3、集合数据类型(List< User >)的注入
package com.kang.poj;
/**
* @ClassName User
* @Description TODO
* @Author kang
* @Date 2022/2/24 下午 4:29
* @Version 1.0
*/
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.kang.impl;
import com.kang.poj.User;
import com.kang.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService {
List<User> list;
public void setList(List<User> list) {
this.list = list;
}
@Override
public void save() {
System.out.println(list);
}
}
<bean id="user1" class="com.kang.poj.User">
<property name="name" value="小红"></property>
<property name="age" value="18"></property>
</bean>
<bean id="user2" class="com.kang.poj.User">
<property name="name" value="小明"></property>
<property name="age" value="20"></property>
</bean>
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<list>
<ref bean="user1"/>
<ref bean="user2"/>
</list>
</property>
</bean>
在配置文件中首先先要配置两个bean实例化的对象,然后将他们放到集合中
5.4、集合数据类型(Map< String, User >)的注入
将5.3的List集合改为Map集合,接着spring的XML文件配置修改为以下
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="list">
<map>
<entry key="第一个人" value-ref="user1"/>
<entry key="第二个人" value-ref="user2"/>
</map>
</property>
</bean>
5.5、集合数据类型(Properties)的注入
package com.kang.impl;
import com.kang.poj.User;
import com.kang.service.UserService;
import java.util.Map;
import java.util.Properties;
/**
* @ClassName UserServiceImpl
* @Description TODO
* @Author kang
* @Date 2022/2/24 上午 9:22
* @Version 1.0
*/
public class UserServiceImpl implements UserService {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public void save() {
System.out.println(properties);
}
}
<bean id="userService" class="com.kang.impl.UserServiceImpl">
<property name="properties">
<props>
<prop key="p1">aaa</prop>
<prop key="p2">bbb</prop>
<prop key="p3">ccc</prop>
</props>
</property>
</bean>
6 、引入其他配置文件
像上面这些配置文件数据要是写在一个配置中会显得这个spring配置文件特别乱
因此,我们可以将部分配置拆分到其他配置文件中,最后通过spring的import标签进行加载
这一有利于分模块开发
命名格式:applicationContext-xxx.xml
<import resource="applicationContext-xxx.xml"/>
7、spring的重点配置(*)
四、Spring相关的API
1、ApplicationContext的实现类
ApplicationContext的实现类有三种
ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件 推荐使用这种
FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。使用该类的时候需要指明配置文件的全路径
AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
2、getBean()方法使用
getBean方法是用来返回Bean实例化的对象,方法重载了两个
public Object getBean(String name) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name); } public <T> T getBean(Class<T> requiredType) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(requiredType); }
public void test02(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// UserService userService = (UserService) app.getBean("userService");
UserService userService = app.getBean(UserService.class);
userService.save();
}
注意:
第一种用法适用于任何情况
第二种用法只适用于id对应的类只有一个的情况,像下面这种情况这无法使用第二种用法,否则会报错,因为程序不知道对应哪一个id
<bean id="user1" class="com.kang.poj.User"> <property name="name" value="小红"></property> <property name="age" value="18"></property> </bean> <bean id="user2" class="com.kang.poj.User"> <property name="name" value="小明"></property> <property name="age" value="20"></property> </bean>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/95023.html