目录
一、什么是框架
高度抽取可重用代码的一种设计,也可以说是多个可重用模块的集合,形成一个某个领域的解决方案。
二、什么是spring框架
①开源框架
②简化企业级开发而生,EJB的升级
③IOC和AOP容器框架
④优良特性:
1、非侵入式:不依赖于API,不需要理解API的每个类每个方法
2、依赖注入
3、面向切面编程
4、容器
5、组件化:把简单的组件配置组合成一个复杂的应用,在spring中可以使用xml和注解组合这些对象
6、一站式:spring可以整合各种优秀的框架和第三方库
三、IOC构造方法创建对象,注入参数,使用反射技术
①获取容器
ApplicationContext: 就是 IOC 容器,通过下面两种方法获得
ClassPathXmlApplicationContext:xml 文件在类路径下
FileSystemXmlApplicationContext:xml 文件在磁盘路径下
②何时创建对象
// 无参构造函数
public Person(){
System.out.println("创建对象");
}
// 注册组件
<bean id="person01" class="cn.imooc.pojo.Person">
<property name="name" value="zhangsan"></property>
<property name="age" value="11"></property>
<property name="sex" value="男"></property>
<property name="email" value="17521648152@163.com"></property>
</bean>
// 测试
@Test
public void test01(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
// Person person =(Person) ioc.getBean("person01");
// System.out.println(person);
}
控制台打印结果
八月 14, 2019 10:01:13 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [ioc.xml]
创建对象
由上面的代码可知,启动容器的时候通过无参构造函数创建了对象,不是ioc.getBean("person01")创建对象,然后注入参数;也就是说容器创建完成的时候容器中的所有对象就已经创建好了,且对象时单实例的,如果没有这个组件,调用ioc.getBean("...."),则会报 notSuchBean 异常
③ 属性赋值
IOC容器在创建组件对象的时候,如果有无参构造器,<property>通过 setter 方法为 javaBean 的属性进行赋值;javaBean属性名由 getter/setter 方法决定的,即 set 后面的内容,首字母要小写
④ ioc.getBean( ) 获取对象的三种方式
Person person =(Person) ioc.getBean("person01");
Person person = ioc.getBean(Person.class);
vPerson person011 = ioc.getBean("person01", Person.class);
如果一个类存在多个 JavaBean 对象,将会出现对象不唯一异常
⑤ 调用有参构造器进行对象创建并赋值
<bean id="person02" class="cn.imooc.pojo.Person">
<constructor-arg name="name" value="lisi"></constructor-arg>
<constructor-arg name="age" value="12"></constructor-arg>
</bean>
不需要调用 setter 方法
⑥ 调用有参构造器不指定属性名
<bean id="person03" class="cn.imooc.pojo.Person">
<constructor-arg value="lisi"></constructor-arg>
<constructor-arg value="12"></constructor-arg>
<!--index 为参数指定索引位置,从0开始-->
<constructor-arg value="17521648152@163.com" index="3"></constructor-arg>
<constructor-arg value="男" index="2"></constructor-arg>
</bean>
index 指定属性索引位置,从0开始
⑦ 重载的情况下用 type 指定参数的类型
public Person(String name, Integer age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public Person(String name, String email, String sex) {
this.name = name;
this.email = email;
this.sex = sex;
}
<bean id="person04" class="cn.imooc.pojo.Person">
<constructor-arg value="lisi"></constructor-arg>
<constructor-arg value="12" type="java.lang.Integer"></constructor-arg>
<constructor-arg value="男"></constructor-arg>
</bean>
输出结果
Person{name='lisi', age=12, sex='男', email='null'}
通过type指定的参数类型选择方法
⑧ P名称空间注入
<!--P名称空间注入-->
<bean id="user01" class="cn.imooc.pojo.User" p:name="wangwu" p:age="11" p:sex="男"></bean>
⑨ 复杂类型注入
<!--复杂类型注入-->
<bean id="student01" class="cn.imooc.pojo.Student">
<!--数组注入-->
<property name="strs">
<array>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</array>
</property>
<!--list集合注入-->
<property name="list">
<list>
<value>ddd</value>
<value>eee</value>
<value>fff</value>
</list>
</property>
<!--set集合注入-->
<property name="set">
<set>
<value>ggg</value>
<value>hhh</value>
<value>iii</value>
</set>
</property>
<!--map集合注入-->
<property name="map">
<map>
<entry key="name1" value="jjj"></entry>
<entry key="name2" value="kkk"></entry>
<entry key="name3" value="lll"></entry>
</map>
</property>
<!--文件内容注入-->
<property name="pro">
<props>
<prop key="name1">mmm</prop>
<prop key="name2">nnn</prop>
<prop key="name3">ooo</prop>
</props>
</property>
</bean>
⑩ 设置参数为空
1、手动设置,对于字符串,整型是不一样的
<bean id="user01" class="cn.imooc.pojo.User">
<!--对于字符串设置<null/>-->
<property name="name" ><null/></property>
<!--对于Integer,设置value=""-->
<property name="age" value=""></property>
<!--对于字符串设置value="",是空字符串""-->
<property name="sex" value=""></property>
</bean>
@Test
public void test1(){
User user01 =(User) ioc.getBean("user01");
System.out.println(user01);
// name为空
System.out.println(user01.getName()==null);
// age为空
System.out.println(user01.getAge()==null);
// sex不为空,为 ""
System.out.println(user01.getSex()==null);
System.out.println(user01.getSex().equals(""));
}
输出结果
User{name='null', age=null, sex=''}
true
true
false
true
2、使用 set 构造方法注入时,如果没有写入参数,默认为 null;ref 引用外部 bean
<!--给 car 注入参数-->
<bean id="car01" class="cn.imooc.pojo.Car">
<property name="carName" value="梅赛德斯"></property>
<property name="price" value="1000"></property>
<property name="color" value="blue"></property>
</bean>
<bean id="user02" class="cn.imooc.pojo.User">
<property name="name" value="lisi"></property>
<!--ref代表引入另外一个组件-->
<property name="car" ref="car01"></property>
</bean>
@Test
public void test2(){
User user02 = ioc.getBean("user02", User.class);
System.out.println(user02.getSex()==null);
System.out.println(user02);
}
输出结果
true
User{name='lisi', age=null, sex='null', car=Car{carName='梅赛德斯', price=1000, color='blue'}}
⑪ 引用内部 bean
<bean id="user03" class="cn.imooc.pojo.User">
<property name="name" value="lisi"></property>
<!--引用内部 bin-->
<property name="car">
<bean class="cn.imooc.pojo.Car">
<property name="carName" value="丰田"></property>
</bean>
</property>
</bean>
⑫ util 名称空间创建集合类型的 bean ,方便其它bean引用
<!--相当于 new linkedHashMap<>()-->
<util:map id="myMap">
<entry key="name1" value="jjj"></entry>
<entry key="name2" value="kkk"></entry>
<entry key="name3" value="lll"></entry>
</util:map>
<!--引用 myMap-->
<bean id="student01" class="cn.imooc.pojo.Student">
<property name="map" ref="myMap"></property>
</bean>
<util:map>,<util:list> , <util:set>等等
⑬ 级联属性:属性的属性
public class User {
private String name;
private Integer age;
private String sex;
private Car car;
......
}
public class Car {
private String carName;
private Integer price;
private String color;
......
}
<!--给 car 注入参数-->
<bean id="car01" class="cn.imooc.pojo.Car">
<property name="carName" value="梅赛德斯"></property>
<property name="price" value="1000"></property>
<property name="color" value="blue"></property>
</bean>
<!--给 user 注入参数-->
<bean id="user05" class="cn.imooc.pojo.User">
<!--引用 car01-->
<property name="car" ref="car01"></property>
<!--改变car的价格-->
<property name="car.price" value="1"></property>
</bean>
@Test
public void test4(){
User iocUser = ioc.getBean("user05", User.class);
System.out.println(iocUser);
}
输出结果
User{name='null', age=null, sex='null', car=Car{carName='梅赛德斯', price=1,
color='blue'}}
⑭ 通过继承实现 bean 配置信息的重用
<!--给 car 注入参数-->
<bean id="car01" class="cn.imooc.pojo.Car">
<property name="carName" value="梅赛德斯"></property>
<property name="price" value="1000"></property>
<property name="color" value="blue"></property>
</bean>
<!--parent: 指定当前 bean 的配置信息继承于哪个-->
<bean id="car02" class="cn.imooc.pojo.Car" parent="car01">
<property name="carName" value="一汽大众"></property>
<!--price color的值 继承 car01-->
</bean>
⑮ 通过 abstrac 属性创建一个模板 bean
<!--给 car 注入参数-->
<!--abstract=true: 这个 bean 的配置是抽象的,只能被继承,不能实例化 -->
<bean id="car01" class="cn.imooc.pojo.Car" abstract="true">
<property name="carName" value="梅赛德斯"></property>
<property name="price" value="1000"></property>
<property name="color" value="blue"></property>
</bean>
⑯ 对象创建顺序
spring 默认按照bean配置的顺序创建bean,通过 depends-on 改变创建顺序
<bean id="book1" class="cn.imooc.pojo.book.Book1" depends-on="book2,book3"></bean>
<bean id="book2" class="cn.imooc.pojo.book.Book2"></bean>
<bean id="book3" class="cn.imooc.pojo.book.Book3"></bean>
四、工厂方法创建对象
① 静态工厂方法
工厂本身不用创建对象,通过静态方法调用,对象=工厂类 . 工厂方法名
public class CarStaticFactory {
private static Car getCar(){
System.out.println("正在生产汽车");
Car car = new Car();
car.setCarName("梅赛德斯");
car.setPrice(100);
car.setColor("blue");
return car;
}
}
<!--facroty-mothod 指定哪个方法是工厂方法-->
<bean id="car01" class="cn.imooc.factory.CarStaticFactory" factory-method="getCar">
<property name="carName" value="奔驰"></property>
</bean>
② 实例工厂方法
先配置实例工厂对象,后调用实例工厂对象的方法
<!--配置实例工厂对象-->
<bean id="carInstanceFactory" class="cn.imooc.factory.CarInstanceFactory"></bean>
<!--factory-bean 指定具体的实例工厂对象-->
<bean id="car02" class="cn.imooc.factory.CarInstanceFactory"
factory-bean="carInstanceFactory" factory-method="getInstanceCar">
</bean>
不管是单例还是多例对象,ioc 容器启动的时候都不主动创建对象,获取的时候才创建对象,单例只创建一个对象,多例则是只要获取就创建一个新的对象
/**
* 1、编写一个FactoryBean的实现类
* 2、注册到 spring 配置文件中
*/
public class MyCarFactoryBean implements FactoryBean<Car> {
/**
* getObject: 工厂方法
* 返回创建的对象
* @return
* @throws Exception
*/
public Car getObject() throws Exception {
System.out.println("myfactory 为你创建对象");
Car car = new Car();
car.setCarName("奔驰");
car.setPrice(1000);
car.setColor("blue");
return car;
}
/**
* 返回创建的对象的类型
* spring会自动调用这个方法来确认创建的对象是什么类型
* @return
*/
public Class<?> getObjectType() {
return Car.class;
}
/**
* 选择是否单例模式
* @return
*/
public boolean isSingleton() {
return true;
}
}
<!--FactoryBean是spring规定的一个接口
它的实现类,spring都认为是一个工厂-->
<bean id="myCarFactoryBean" class="cn.imooc.factory.MyCarFactoryBean"></bean>
五、对象的作用域和生命周期
当使用构造方法和工厂方法创建对象:
1、单例对象:容器启动的时候对象就被创建,对象会一直存在,容器销毁的时候,对象被回收
2、多例对象:容器启动的时候不主动床架对象,只有当获取对象的时候才创建对象,每次获取的时候都会创建一个新的 实例对象,需要手动回收对象
public class Car {
private String carName;
private Integer price;
private String color;
public Car() {
System.out.println("创建car对象");
}
public void destroy(){
System.out.println("对象销毁");
}
public void init(){
System.out.println("对象创建");
}
}
<!--设置销毁、初始化方法-->
<bean id="car06" class="cn.imooc.pojo.Car"
destroy-method="destroy" init-method="init" >
</bean>
@Test
public void test1(){
ConfigurableApplicationContext ioc = new
ClassPathXmlApplicationContext("ioc1.xml");
Object car06 = ioc.getBean("car06");
ioc.close();
System.out.println(car06);
}
输出结果:
创建car对象
对象创建
对象销毁
Car{carName='null', price=null, color='null'}
六、Bean的后置处理器
public class InitCar implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化对象初始化之前");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在对象初始化之后");
return bean;
}
}
public class Car {
private String carName;
private Integer price;
private String color;
public Car() {
System.out.println("创建car对象");
}
public void destroy(){
System.out.println("对象销毁");
}
public void init(){
System.out.println("对象初始化");
}
<!--设置销毁、初始化方法-->
<bean id="car06" class="cn.imooc.pojo.Car"
destroy-method="destroy" init-method="init" >
</bean>
<!--后置处理器实现类-->
<bean class="cn.imooc.beanPostProcessor.InitCar"></bean>
输出结果:
创建car对象
在初始化对象初始化之前
对象初始化
在对象初始化之后
对象销毁
Car{carName='null', price=null, color='null'}