Spring介绍
框架:高度抽取可重用代码的一种设计;高度的通用性;
多个可重用模块的集合,形成某个领域的整体解决方案
Spring框架:容器:可以管理所有的组件;IOC和AOP
IOC(容器):Iversion Of Control 控制反转
用容器来整合框架
控制:资源的获取
- 主动式(自己用什么资源就创建new)
- 被动式(资源的获取交给容器创建和设置)
容器:从主动的new资源为被动的接受资源
DI(Dependency Injection):依赖注入(是IOC思想的具体实现)。容器能知道那个组件运行的时候,需要另一个组件,容器通过反射的形式,将容器中的准备好的对象注入(利用反射给属性赋值)到最初的那个组件中。
容器中对象的创建在容器创建的时候就创建了。
一个bean对应一个对象
同一个组件在ioc中是单例的。
javabean的属性名是由getter/setter方法决定的,去掉set之后将首字母小写之后得到的字符串就是属性名。
配置文件:
bean的创建原理
bean的创建就是框架利用反射new出来的bean实例
话说反射是一种效率很低的方法,所以有哪些对象是应该使用bean来创建的呢?
<?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="stu1" class="com.onezero.Student">
<property name="name" value="张三"></property>
<property name="age" value="18"></property>
</bean>
<bean id="stu2" class="com.onezero.Student">
<property name="name" value="李四"></property>
<property name="age" value="19"></property>
</bean>
<bean id="stu3" class="com.onezero.Student">
<constructor-arg name="age" value="20"></constructor-arg>
<constructor-arg name="name" value="onezero"></constructor-arg>
</bean>
<bean id="stu4" class="com.onezero.Student">
<constructor-arg value="马云"></constructor-arg>
<constructor-arg value="40"></constructor-arg>
</bean>
</beans>
在配置文件中使用property标签是通过set方法来赋值的。通过constructor-arg可以调用有参构造器赋值。若是严格按照有参构造器中参数出现的顺序写属性,则可以省略name。
若没有严格按照构造器中给出的参数数据赋值,可以通过index指定赋给第几个参数。
若是构造器进行了重载且参数个数一样,如果想省略name需要指定type(即参数类型)
综上所述,不省略name是一种比较常见的配置方法。
通过p命名空间为bean赋值
通过get/set方法进行赋值
<?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="stu05" class="com.onezero.Student" p:age="19" p:name="小红"></bean>
</beans>
获取bean对象的三种方法:
//通过bean的id获取bean的实例
public void dmeo() {
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc.xml");
System.out.println("ioc配置完成");
Student stu1 = (Student) ac.getBean("stu1");
System.out.println(stu1);
}
//通过bean的类型从IOC容器中获取bean的实例,优点是可以不用进行类型转换,缺点是若配置文件中存在多个该类型的bean,就会报错
public void demo2(){
Student stu = ac.getBean(Student.class);
System.out.println(stu);
}
//改进
Student stu = ac.getBean("stu1",Student.class);
通过配置文件进行复杂的赋值:
package com.onezero;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Student {
private String name;
private Integer age;
private Car car;
private List<Book> list;
private Map<String,Object> map;
private Set<Integer> set;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
", list=" + list +
", map=" + map +
", set=" + set +
", properties=" + properties +
'}';
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
public Set<Integer> getSet() {
return set;
}
public void setSet(Set<Integer> set) {
this.set = set;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
private Properties properties;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public List<Book> getList() {
return list;
}
public void setList(List<Book> list) {
this.list = list;
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("有参");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Student() {
System.out.println("对象被创建了");
}
}
<?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"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="stu" class="com.onezero.Student">
<property name="age" value="19"></property>
<property name="name">
<null></null>
</property>
<!--ref:引用外部bean,是严格的引用-->
<property name="car" ref="car"></property>
<property name="list">
<!--为list赋值-->
<list>
<!--内部bean无法被外部获取到-->
<bean class="com.onezero.Book" p:name="西游记" p:author="吴承恩" p:price="20"></bean>
<!--使用外部引用-->
<ref bean="book1"></ref>
</list>
</property>
<property name="map">
<map>
<entry key="book" value-ref="book1"></entry>
<entry key="name" value="小红"></entry>
<entry key="num">
<value>126</value>
</entry>
</map>
</property>
<property name="set">
<set>
<value>15</value>
<value>15</value>
<value>155</value>
</set>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
<bean id="car" class="com.onezero.Car">
<property name="branch" value="宝马"></property>
<property name="price" value="300000"></property>
</bean>
<bean id="book1" class="com.onezero.Book" p:price="30" p:author="金鱼酱" p:name="人间告白">
</bean>
</beans>
通过util命名空间创建集合类型的bean,方便引用
<!--util:map相当于new了一个LinkedHashMap-->
<util:map id="map">
<entry key="book" value-ref="book1"></entry>
<entry key="name" value="小红"></entry>
<entry key="num">
<value>126</value>
</entry>
</util:map>
<bean id="stu2" class="com.onezero.Student">
<property name="map" ref="map"></property>
</bean>
级联属性
级联属性:属性的属性(例如:car.price)
parent属性
parent:指定当前的bean的配置信息继承于哪个bean
abstract=“true”
abstract=“true”:表示当前bean的配置是一个抽象的,不能获取它的实例,只能被继承
depends-on:bean之间的依赖
bean 里面的依赖只是指bean的创建顺序罢了。若是没有依赖,创建顺序按照在配置文件中的书写顺序。若是有了依赖关系,那么先创建被依赖的bean(被依赖的bean可以是有多个)
bean的作用域
bean的作用域指bean是否是单实例的。默认情况下,bean是单实例的。
scope=“prototype”:多实例
- 容器启动时默认不去创建多实例的bean
- 获取的时候这个bean才会创建
- 每次获取都创建一个新的对象
scope=“singleton”:单实例(默认)
- 在容器启动完成之前就创建好了对象,保存到容器
- 获取到的bean一直是一样的
静态工厂和实例工厂
工厂模式:工厂帮我们创建对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
- 静态工厂:工厂本身不用创建对象,通过静态方法调用
- factory-method:使用静态工厂中的那个方法
- 实例工厂:工厂本身需要创建对象
- factory-bean:指定使用哪个工厂
- factory-method:使用静态工厂中的那个方法
<!--静态工厂方法创建bean-->
<bean id="stu1" class="com.onezero.factory.StaticFactory" factory-method="getStudent">
<constructor-arg value="李四"></constructor-arg>
</bean>
<!--实例工厂创建bean-->
<bean id="stuFactory" class="com.onezero.factory.InstanceFactory"></bean>
<bean id="stu2" class="com.onezero.Student" factory-bean="stuFactory" factory-method="getStudent">
<constructor-arg value="张三"></constructor-arg>
</bean>
-
FactoryBean是Spring的一个接口,只要是这个接口的实现类,Spring就认为这是个工厂类
步骤:写一个实现类;在spring中配置
public class MyFactory implements FactoryBean<Book> { @Override public Book getObject() throws Exception { System.out.println("创建一个实例"); Book book=new Book(); return book; } @Override public Class<?> getObjectType() { return Book.class; } }FactoryBean:获取的时候才创建实例;ioc启动的时候不会创建实例
bean的生命周期
单实例的bean容器启动时就创建好,容器关闭就会销毁创建的bean
多实例bean获取是才会创建。
在spring中也可以通过方法来指定生命周期。
单例bean的生命周期:构造器–初始化方法–(容器关闭)销毁方法
多例bean的生命周期:(获取bean)构造器–初始化方法 就算是容器关闭也不会调用销毁方法
<bean id="book" class="com.onezero.Book" init-method="init" destroy-method="destory" scope="prototype"></bean>
private ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("ioc5.xml");
//ApplicationContext接口中没有close方法
bean的后置处理器
后置处理器:可以在bean的初始化前后调用方法。
使用步骤:实现 BeanPostProcessor接口;在配置文件中注册
public class BeanPostProcessorTest implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName+":将要调用初始化方法.这个bean是"+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return null;
}
}
<bean id="beanPostProcessor" class="com.onezero.test.BeanPostProcessorTest"></bean>
引用外部属性文件
数据库连接池作为单实例是最好的,一个项目就一个连接池。
<context:property-placeholder location="classpath:durid.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${usernameH}"></property>
<property name="password" value="${password}"></property>
<property name="url" value="${url}"></property>
<property name="driverClassName" value="${driver}"></property>
</bean>
因为username是Spring中的关键字,所以在.properties时不能使用username,可以改为jdbc.username
自动装配
autowired(xml)
- byType
- byName
- constructor
通过注解@Autowored实现自动装配,它可以用于成员变量、构造器及方法,不过只能用于装配引用。
SpEL:Spring Expression Language
#{}
${}
//调用静态方法
#{T(全类名).方法}
通过注解将bean加入容器
- @Component
- @Repository:持久层
- @Controller:控制层
- @Service:业务层
之后要在xml中加入
<context:component-scan base-package=""/>
Spring 会扫描所有base-package下的类。

本文详细介绍了Spring框架中的IOC(控制反转)概念,包括通过XML配置文件创建bean、依赖注入、bean的作用域、静态工厂和实例工厂的使用、bean的生命周期以及后置处理器等。此外,还讨论了注解在Spring中的应用,如@Component、@Repository、@Controller和@Service,并提到了SpEL(Spring Expression Language)在配置中的作用。
7245

被折叠的 条评论
为什么被折叠?



