Spring-day1-快速开始和注入
Spring
概述
javaEE全站的轻量级开源框架,以IOC(Inverse of control:反转控制)和AOP(Aspect Oriented Programming 面向切面编程)为内核。
工厂模式创建对象
问题:在项目运行时,需要手动导入bean对象,但是在运行时可能会找不到文件等情况出现编译错误错误。
解决:使用工厂类来创建对象,降低依赖调用的耦合,避免产生编译错误。
步骤:
- 配置文件有xml或properties两种。利用静态代码块加载配置文件
- 导入配置文件时要用
className.class.getClassLoader().getResourceAsStream("文件名")
来读取文件流 - 读取到配置文件后用
class.forName(配置文件中类的全路径).newInstance()
创建一个bean类,要用一个map容器来存储创建的类,使之成为单例模式。
避免了app自己寻找资源,而是通过工厂来找资源,削减了计算机程序的耦合,接触了代码依赖关系。
快速开始
-
maven导入spring-context
-
在main-resources建立bean.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
-
在xml中导入自己写的功能组件
<bean id="accountService" class="web.service.impl.accountServiceImpl"></bean> <bean id="accountDao" class="web.dao.impl.accountDaoImpl"></bean>
-
在主方法中(用户操作自己账户)
public class Client { /* * 获取spring的ioc核心容器根据id获取对象 * ApplicationContext的三个实现类 * ClassPathXmlApplicationContext 它可以加载类路径下的配置文件,要求必须在类路径下 * FileSystemXmlApplicationContext 可以加载任意路径下的配置文件,必须有访问权限 * AnnotationConfigApplicationContext 用于读取注解创建容器的 * * */ public static void main(String[] args) { // 1.获取核心容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 2.根据id获取bean对象 I_AccountService aservice = (I_AccountService) ac.getBean("accountService"); I_AccountDao adao = ac.getBean("accountDao", I_AccountDao.class); System.out.println(aservice); System.out.println(adao); } }
- 核心容器的两个接口引发出的问题
- ApplicationContext:创建核心容器是,创建对象采取的策略是立即加载的方式,也就是一读取配置文件马上就创建配置文件中配置的对象。(单例对象创建适用)
- BeanFactory: 创建对象采取的策略是采用延迟加载的方式,也就是什么时候根据id获取对象了,什么时候才真正创建对象。(多例对象创建适用)
- 核心容器的两个接口引发出的问题
bean对象
-
创建bean的三种方式
-
使用默认构造函数创建:使用bean标签,配以id和class属性后,且没有其他属性和标签。如果类中没有构造函数,则对象无法创建。默认为空参构造
<bean id="accountService" class="web.service.impl.accountServiceImpl"></bean>
-
使用某个类中的方法创建对象
<bean id="工厂类id" class="全路径"></bean> <bean id="类id" factory-bean="上方工厂类id" factory-method="创建类的方法"></bean>
-
使用工厂中的静态方法创建对象
<bean id="工厂类id" class="全路径"></bean> <bean id="类id" factory-bean="上方工厂类id" factory-method="静态方法"></bean>
-
-
bean的作用范围
bean标签的scope属性
- singleton 默认属性 单例
- prototype 多例
- request 作用于web应用的请求范围
- session 作用于web应用的会话
- Global-session 作用于集群,当不是集群时,就是session
-
bean对象的生命周期
-
单例
和容器生命周期相同
-
多例
使用对象时spring框架来创建,对象在使用就一直存在,当对象长时间不用,且没有别的对象引用时,有java的垃圾回收器回收。
-
<bean id="accountService" class="web.service.impl.accountServiceImpl"
scope="",
init-method="初始化方法",
destroy-method="结束方法"
></bean>
- 如果一个类引用了另一个类,那么在xml文件中就要用property去引用他。
- 连接数据库的信息也在bean中注入,包括账号密码
依赖注入
能注入的数据有三类
- 基本类型和String
- 其他bean类型,配置文件或注解配置的bean
- 复杂类型/集合类型
注入的方式
某个类构造方法如下:
public accountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
-
使用构造函数提供(不推荐使用,看弊端)
使用的标签:constructor-arg,出现在bean内部
属性:
- type:要注入的数据的数据类型,是构造函数中某个或谬写参数的类型
- index:用于指定要注入的数据给构造函数中索引位置赋值
- name:用于指定给构造函数中指定名称的参数赋值
- value:基本类型和string类型
- ref:指定其他类型数据,指的是spring的Ioc核心容器出现过的bean对象
<bean id="accountService" class="web.service.impl.accountServiceImpl"> <constructor-arg name="name" value="jack"/> <constructor-arg name="age" value="13"/> <constructor-arg name="birthday" value="2012-12-12"/> //会报错 ============================================== <constructor-arg name="birthday" ref="now"/> </bean> <bean id="now" class="java.util.Date">
- 优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
- 弊端:改变了bean对象的实例化方式,在创建对象时,如果用不到也必须提供
-
使用set方法提供(常用方式)
涉及的标签:property 出现的位置bean标签的内部
标签的属性
- name 用于指定注入时所调用的set方法名称
- value
- ref
<bean id="accountService" class="web.service.impl.accountServiceImpl"> <property name="name",value="test"></property> </bean> <bean id="now" class="java.util.Date">
优势:创建对象没有明确的限制,可以直接使用默认构造函数
劣势:如果有某个成员必须有值,则获取对象有可能set方法没有执行
-
复杂类型注入如list array set 结构相同,标签可以互换。map props同样
<property name="name",value="test"> <array name=Array对象名称> <value>aaaa1</value> <value>aaaa3</value> <value>aaaa2</value> </array> <map name=Map对象名称> <entry key="a" value=1></entry> </map> <props> <prop key="b">c</prop> </props> </property>
-
使用注解提供
-
用于创建对象的(在实现类上添加)
作用和xml文件中编写bean标签功能相同
- @component
类文件 @Component("accountService") public class accountServiceImpl implements I_AccountService { // 如果经常变化的数据,并不适用于注入的方式 private String name; private Integer age; private Date birthday; // public accountServiceImpl(String name, Integer age, Date birthday) { // this.name = name; // this.age = age; // this.birthday = birthday; // } public void saveAcount() { System.out.println("service 方法执行"+name+age+birthday); } } 配置文件: <?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> // 告知spring在创建容器要扫描的包 <context:component-scan base-package="目录"></context:component-scan> </beans> 应用层://getBean后面接的是bean的id,component也是bean I_AccountService aservice = (I_AccountService) ac.getBean("accountService");
作用:用于把当前类对象存入spring容器中
属性:value用于指定bean的id,默认值是当前类名小写
一下三个注解作用和属性和component一模一样
- Controller:一般用在表现层
- Service:一般用在业务层
- Repository:一般用在持久层
-
用于注入数据的
作用就合bean标签中property作用相同
-
Autowired
@Autowired private I_AccountDao accountDao = null; public void saveAccount() { accountDao.b();
作用:自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配成功,就可以成功注入。如果匹配到了两个相同的实现类,就根据变量名在去匹配beanid,如果变量名两者不匹配则报错。
位置:可以是变量或方法
注意:只能匹配一个,如果有多个会报错
-
Qualifier
作用:按照类型注入的基础上再按照名称注入。在给类成员注入时不能单独使用,可以给方法参数注入。
属性:value用于指定注入bean的id
@Autowired @Qualifier("dao1") private I_AccountDao accountDao = null; public void saveAccount() { accountDao.b();
-
Resource
作用:直接按照bean的id注入,可以独立使用
属性:name 用于指定bean的id
@Resource(name="dao2") private I_AccountDao accountDao = null; public void saveAccount() { accountDao.b();
以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型都无法通过以上方式实现。另外集合只能通过xml的方式注入。
- Value
作用:用于注入基本类型和String类型的数据
属性:用于指定数据的值 value,常用取值singleton prototype
-
-
用于改变作用范围的
作用就合bean标签中scope作用相同
-
和生命周期相关
作用就合bean标签中init-method,destroy-method作用相同
-
注解类替换xml文件
配置类
@Configuration //当配置类需要被扫描时(通过ComponentScan配置的)该注解不可以省略
@ComponentScan(basePackages = "web")
public class SpringConfiguration {
@Bean(name="runner")
// 用于把当前方法的返回值作为bean对象存入spring ioc容器中
// 属性:
// name:用于指定bean的id,默认值时当前方法的id
// 注意: 如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找的方式和autowired一样
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
}
应用层
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class); //可省略该类的configuration注解
// 2.根据id获取bean对象
I_AccountService aservice = (I_AccountService) ac.getBean("accountService");
I_AccountDao adao = ac.getBean("accountDao", I_AccountDao.class);
aservice.saveAccount();
-
Import注解
作用:导入其他的配置类。既不需要在获取配置类事导入字节码
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class)
也不需要通过加Component和ComponentScan扫描
属性:
value:用于指定其他配置类的字节码。使用Import注解后,有Import的类就是父配置类,而导入的都是子配置类。
-
PropertySource注解
作用:导入properties里面的配置
属性:value指定文件的名称和路径
@ComponentScan(basePackages = "web")
@import(jdbcConfig.class)
@PropertySource("classpath:config/spring/jdbcConfig.properties")
public class SpringConfiguration {
@Bean(name="runner")
// 用于把当前方法的返回值作为bean对象存入spring ioc容器中
// 属性:
// name:用于指定bean的id,默认值时当前方法的id
// 注意: 如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找的方式和autowired一样
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
}
在jdbcConfig中,用value去对应表达式的值,@PropertySource已经找到了配置文件
@Value("${jdbc.driver}")
private String driver;