练习题
实验一 | 通过IOC容器创建对象,并为属性赋值
实验二 | 通过Bean的类型从IOC中获取bean的实例
实验三
3.1使用构造器在IOC中创建bean
3.2通过p名称空间为bean赋值
实验四
4.1正确的为各种属性赋值 测试使用nu11值、 引用类型赋值(引用其他bean、引用内部bean) 集合类型赋值(List、Map、 Properties)
4.2 Util名称空间创建集合类型的bean
4.3级联属性赋值
实验五 | 通过继承实现配置信息的重用
实验六 | 通过abstract属性创建一个模板bean
实验七 | Bean之间的依赖
实验八 | 测试bean的作用域
★实验九
实验十 | 创建带有生命周期方法的bean
实验十一 | 测试bean的后置处理器
★实验十二 | 引用外部属性文件(spring管理连接池)
实验十三 | 基于XML的自动装配(自动赋值)
实验十四 SPEL测试
★实验十五 | 使用注解分别创建Dao,Service,Controller
实验十六 | 指定扫描时不包含的类
实验十七 | 指定扫描时要包含的类
★实验十八 | 使用@Autowired注解实现根据类型的自动装配
★实验十九 | 资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean
★实验二十 | 使用@Qualifier注解明确指定目标bean的id
★实验二十一 | 在方法的形参上使用@Qualifier注解
★实验二十二 | @Autowired注解的required属性指定某个属性允许不被设置
TOC
练习题
实验一 | 通过IOC容器创建对象,并为属性赋值
ico.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="person01" class="per.wzy.spring.Person">
<property name="age" value="18"></property>
<property name="name" value="张三"></property>
<property name="sex" value="男"></property>
</bean>
</beans>
test.java
public class ioctest {
@Test
public void Test(){
//创建容器对象
//容器中的对象在容器创建完成的时候就已经创建好了(所有的对象都会创建)
//同一组件在IOC中是单实例的
ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
//获取对象
Person person01 = (Person) context.getBean("person01");
System.out.println(person01.getName());
}
}
实验二 | 通过Bean的类型从IOC中获取bean的实例
//如果IOC容器中这个类型的bean有多个,则查找会报错
Person person = context.getBean(Person.class);
//存在多个同类型bean,根据id查找
Person person = context.getBean("person02",Person.class);
实验三
3.1使用构造器在IOC中创建bean
<bean id="person03" class="per.wzy.spring.Person">
<constructor-arg name="name" value="大花"></constructor-arg>
<constructor-arg name="age" value="19"></constructor-arg>
<constructor-arg name="sex" value="女"></constructor-arg>
</bean>
- 不添加name属性,默认按照构造器中属性顺序赋值
- 添加index属性,设置位置
- 添加type属性,设置值的类型,适用于构造器重载的情况
3.2通过p名称空间为bean赋值
引入p名称空间:beans中添加 xmlns:p="http://www.springframework.org/schema/p"
使用p名称空间进行赋值
<bean id="person05" class="per.wzy.spring.Person" p:age="15" p:name="二花" p:sex="母猪"> </bean>
实验四
4.1正确的为各种属性赋值 测试使用nu11值、 引用类型赋值(引用其他bean、引用内部bean) 集合类型赋值(List、Map、 Properties)
**复杂属性赋值**
<bean id="person06" class="per.wzy.spring.Person">
<constructor-arg name="age" value="16"></constructor-arg>
<!--地址引用 bean-->
<!--<constructor-arg name="child" ref="chid01"></constructor-arg>-->
<constructor-arg name="child">
<!--对象使用bean标签进行创建-->
<bean class="per.wzy.spring.Children">
<property name="sex" value="女"></property>
<property name="name" value="翠花"></property>
<property name="age" value="2"></property>
</bean>
</constructor-arg>
<constructor-arg name="childrens">
<list>
<bean id="child02" class="per.wzy.spring.Children" p:sex="男" p:name="王五" p:age="18"></bean>
<ref bean="chid01"></ref>
</list>
</constructor-arg>
<constructor-arg name="name" value="三花"></constructor-arg>
<constructor-arg name="sex" value="女"></constructor-arg>
<!--MAP属性赋值-->
<constructor-arg name="map">
<map>
<entry key="key01">
<bean class="per.wzy.spring.Children" p:age="18" p:name="华盛顿" p:sex="男"></bean>
</entry>
</map>
</constructor-arg>
<constructor-arg name="properties">
<props>
<prop key="username">wzy</prop>
<prop key="pwd">123456</prop>
</props>
</constructor-arg>
</bean>
- 赋NULL值,不填写value属性,添加标签
- 复杂属性赋值均不在value中进行赋值
- List赋值:添加标签,标签中继续添加其他标签
4.2 Util名称空间创建集合类型的bean
<!--添加命名空间导入提示 --> xmlns:context="http://www.springframework.org/schema/context
导入util命名空间
<util:map id="map01"> <entry key="key001"> <bean class="per.wzy.spring.Children"> <!--<constructor-arg name="age" value="15"></constructor-arg>--> <!--<constructor-arg name="name" value="函数"></constructor-arg>--> <!--<constructor-arg name="sex" value="男"></constructor-arg>--> <property name="name" value="111"></property> <property name="sex" value="男"></property> <property name="age" value="150"></property> </bean> </entry></util:map>
4.3级联属性赋值
级联属性:属性的属性
<bean name="person07" class="per.wzy.spring.Person">
<property name="child" ref="chid01"></property>
<property name="child.age" value="20"></property>
</bean>
引用会更改原来bean中的值
实验五 | 通过继承实现配置信息的重用
parent:指定当前bean的配置信息继承于哪个bean
<bean name="person08" class="per.wzy.spring.Person" parent="person06"> <property name="name" value="哈子"></property></bean>
实验六 | 通过abstract属性创建一个模板bean
abstract="true" :这个bean的配置是抽象的,不能获取他的实例,只能用来被继承。
<bean name="person08" class="per.wzy.spring.Person" abstract="true"> <property name="name" value="继承"></property> <property name="age" value="11"></property> <property name="sex" value="男"></property></bean>
实验七 | Bean之间的依赖
- 原本是按照bean的配置顺序创建
- 使用depends-on决定创建顺序
实验八 | 测试bean的作用域
测试bean的作用域,分别创建单实例和多实例的bean
bean的作用域:指定bean是否单实例,xxx;默认:单实例的
prototype:多实例的
1)、容器启动默认不会去创建多实例bean
2)、获取的时候创建这个bean,每次获取创建一个新的
sing1eton:单实例的;默认的
1)、在容器启动完成之前就已经创建好对象,保存在容器中了。
2)、任何获取都是获取之前创建好的那个对象
★实验九
配置通过静态工厂方法创建的bean,实例工厂方法创建的bean、FactoryBean
bean的创建默认就是框架利用反射new出来的bean实例
<!--1、静态工厂(不需要创建工厂本身) Factory- method=" getAirP1ane"
指定哪个方法是工厂方法
class:指定静态工厂全类名
factory- method:指定工厂方法
package per.wzy.factory;
import per.wzy.spring.Car;
public class CarStaticFactory {
public static Car getCar(String name){
Car car = new Car();
car.setName(name);
car.setColor("Red");
car.setPrice(95650.5);
return car;
}
}
<bean name="car01" class="per.wzy.factory.CarStaticFactory" factory-method="getCar">
<constructor-arg name="name" value="崩瓷"></constructor-arg>
</bean>
实例工厂方法创建bean对象
<!--配置实例工厂-->
<bean name="CarInterFace" class="per.wzy.factory.CarInterfaceFactory"></bean>
<!--使用实例工厂创建bean对象-->
<!--使用 constructor-arg 给工厂方法负责-->
<bean name="car02" class="per.wzy.spring.Car" factory-bean="CarInterFace" factory-method="getCar">
<constructor-arg name="name" value="奥迪"></constructor-arg>
</bean>
实验十 | 创建带有生命周期方法的bean
package per.wzy.spring;
public class Book {
private String bookname;
private String isbn;
private double price;
//自定义初始化方法,不能带有参数,但可以抛出任意异常
public void Init(){
System.out.println(" book init ......");
}
//销毁方法
public void Destory(){
System.out.println("book destory ......");
}
public Book() {
}
public Book(String bookname, String isbn, double price) {
this.bookname = bookname;
this.isbn = isbn;
this.price = price;
}
public String getBookname() {
return bookname;
}
public void setBookname(String bookname) {
this.bookname = bookname;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
<!--单实例bean:容器启动时自动创建-->
<!--多实例bean: 容器启动时不会被创建,获取时创建-->
<!--为bean自定义一些生命周期方法,创建或销毁时会使用这些方法-->
<bean id="book01" class="per.wzy.spring.Book"
destroy-method="Destory"
init-method="Init">
<property name="bookname" value="Java编程"></property>
<property name="isbn" value="ki154454"></property>
<property name="price" value="15.3"></property>
</bean>
实验十一 | 测试bean的后置处理器
无论bean是否具有初始化方法,后置处理器都会执行
流程:
编写后置处理器实现类
package per.wzy.spring;
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName+"即将初始化"); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName+"初始化完成"); return bean; }
}
后置处理器注册在配置文件中
输出结果:
八月 31, 2019 4:06:46 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5cbc508c: startup date [Sat Aug 31 16:06:46 CST 2019]; root of context hierarchy
八月 31, 2019 4:06:47 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
book01即将初始化
book init ......
book01初始化完成
八月 31, 2019 4:06:48 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@5cbc508c: startup date [Sat Aug 31 16:06:46 CST 2019]; root of context hierarchy
book destory ......
★实验十二 | 引用外部属性文件(spring管理连接池)
context命名空间
xmlns:context="http://www.springframework.org/schema/context"
````
xsi中添加
```xml
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
外部配置文件
user=root
password=www123
jdbcUrl=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver
<!--引用外部属性文件,依赖context名称空间-->
<!--classpath:应用类路径下资源-->
<context:property-placeholder location="dbconfig.properties"></context:property-placeholder>
<!--引用外部属性文件(spring管理连接池)-->
<!-- ${key} 动态取出配置文件中键对应的值 -->
<!--username 是spring中的关键字,key不能设为username-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="driverClass" value="${driverClass}"></property>
</bean>
实验十三 | 基于XML的自动装配(自动赋值)
自动装配《仅对自定义类型的属性有效,基本类型无法赋值》
autowire="default/no" 不自动装配,默认情况
autowire="byName" 按照名字寻找,以属性名作为id去容器中找到组件,并赋值。找不到则为null
autowire="byType" 以类型作为依据去容器中查找组件,若不唯一则产生错误。若没找到对应,装配null
autowire="constructor"
按构造器进行赋值
1)、先按照有参构造器的参数类型进行匹配(成功赋值),不成功则赋值null
2)、如果按照类型找到了多个;以参数名作为id进行匹配,找到赋值,找不到则赋值null
3)、不会产生报错
<bean id="person01" class="per.wzy.spring.Person" autowire="constructor"></bean>
实验十四 SPEL测试
在SpEL中使用字面量
引用其他bean
引用其他bean的某个属性值
调用静态方法 #{T(全类名).静态方法名}
调用非静态方法
<bean id="person02" class="per.wzy.spring.Person"> <property name="book" value="#{book01}"></property> <!--调用静态方法--> <property name="name" value="#{T(java.util.UUID).randomUUID().toString()}"></property> <!--调用非静态方法--> <property name="age" value="#{person01.getAge()}"></property> </bean>
★实验十五 | 使用注解分别创建Dao,Service,Controller
某个类上添加上任何一个注解都能快速的将这个组件加入到ioc容器的管理中
Spring有四个注解
@Controller:控制器;我们推荐给控制器层(serv1et包下的这些)的组件加这个注解
@Service:业务逻辑;我们推荐业务逻辑层的组件添加这个注解; Bookservice
@Repository:给数据库层(持久化层,dao层)的组件添加这个注解
@Component:给不属于以上几层的组件添加这个注解
注解可以随意添加。spring底层不会验证该组件
步骤:
给要添加的组件上添加上述四个注解的一个
告诉Spring,自动扫描添加了注解的组件,依赖context名称空间
一定要导入aop包(支持注解模式)
<context:component-scan base-package="per.wzy">
使用注解加入到容器中的组件,和使用配置加入到容器中的组件行为都是默认一样的;
1、组件的id。默认就是组件的类名首字母小写
2、组件的作用域,默认就是单例的;
public class SpringTest {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext2.xml");
@Test
public void test(){
Object booksql = applicationContext.getBean("bookSql");
Object booksql1 = applicationContext.getBean("bookSql");
System.out.println(booksql==booksql1); //true
}
注解后课添加(”XXX“)更改默认名称 || @Repository("bok")
添加Scope注解更改单/多实例 || @Scope(value = "prototype")
实验十六 | 指定扫描时不包含的类
<context:component-scan base-package="per.wzy">
<!--通过注解判断是否添加进容器,指定注解不添加包含此注解的类-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
<!--通过类指定不添加到容器中-->
<context:exclude-filter type="assignable" expression="per.wzy.service.BookService"></context:exclude-filter>
</context:component-scan>
实验十七 | 指定扫描时要包含的类
必须禁用默认的扫描规则
<context:component-scan base-package="per.wzy" use-default-filters="false">
<!-- use-default-filters="false" 禁用默认的扫描规则-->
<context:include-filter type="assignable" expression="per.wzy.service.BookService"></context:include-filter>
</context:component-scan>
★实验十八 | 使用@Autowired注解实现根据类型的自动装配
bookSql.java
@Repository
public class bookSql {
public void bookSave(){
System.out.println("svae book....");
}
}
BookService.java
@Service
public class BookService {
@Autowired
private bookSql bsql; //自动装配
public void bookAdd(){
bsql.bookSave();
}
}
BookServlet.java
@Controller
public class BookServlet {
@Autowired
private BookService service;
public void get(){
service.bookAdd();
}
}
测试方法
public class SpringTest {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext2.xml");
@Test
public void test(){
BookServlet bean = applicationContext.getBean(BookServlet.class);
bean.get();
}
}
输出:
svae book....
★实验十九 | 资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean
@Autiwired 原理
先按照类型去容器中寻找对应的组件
找到一个,进行赋值
没有找到,抛出异常
找到多个,按照变量名作为id继续匹配。若没有对应匹配,报错
- 原因(依据变量名进行匹配)
- 解决:使用@Qualifier(value = "bookService")指定字符串作为id
@Controller public class BookServlet {
@Qualifier(value = "bookService") @Autowired private BookService service2; public void get(){ service2.bookAdd(); }
}
★实验二十 | 使用@Qualifier注解明确指定目标bean的id
使用@Qualifier(value = "bookService")指定字符串作为id
@Controller
public class BookServlet {
@Qualifier(value = "bookService")
@Autowired
private BookService service2;
public void get(){
service2.bookAdd();
}
}
★实验二十一 | 在方法的形参上使用@Qualifier注解
/**
* 方法上有autowired注解
* 1.该方法会在bean创建时自动运行
* 2.这个方法上的每一个参数都会自动注入值
* @param service
* @param bookSqls
*/
@Autowired
public void limengkeShabi(BookService service, @Qualifier(value = "bookSql") bookSql bookSqls){
System.out.println("BookService:"+service+" bookSql:"+bookSqls);
}
★实验二十二 | @Autowired注解的required属性指定某个属性允许不被设置
@Controller
public class BookServlet {
@Qualifier(value = "bookService")
@Autowired(required = false)
private BookService service3;
public void get(){
System.out.println("services3....."+service3);
// service3.bookAdd();
}
}
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
======
======