1.Spring作用:
1.生态体系庞大,全能型选手!【springmvc是其一个子模块,jdbcTemplate能直接操作数据库!】2.将其他组件粘合在一起
3.IOC容器和AOP[Aspect Oreinted Programming]:
Spring的Ioc[Inverse of Controller]机制(控制反转和依赖注入)正是用在此处。
Spring的Ioc(控制反转和依赖注入)
控制反转[Ioc]:就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。
控制反转是一种思想,其具体实现就是依赖注入!
依赖注入[DI:Dependency Injection]:组件之间的依赖关系由容器在运行期决定,由容器动态的将某种依赖关系注入到组件之中。
2.IOC容器细节
1.使用IOC容器创建对象2.使用IOC容器在创建对象的同时,给对象的属性赋值
3.在创建对象的过程中,实现组件对象之间的自动装配
3.搭建Spring IOC容器需要的开发环境
1.导入IOC容器需要的jar包spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
commons-logging-1.1.3.jar https://pan.baidu.com/s/1pKQznR1
2.创建Spring配置文件[Spring bean Configuration File]
4.配置bean实验
1.
<!-- class指定类对象的全类名,交给服务器创建一个对象,id是唯一标识,在IOC只能出现一个id值为book01的对象 -->
<bean id="book01" class="com.neuedu.spring.entity.Book">
<property name="name" value="1984"></property>
<property name="author" value="乔治奥威尔"></property>
<property name="price" value="35.0"></property>
</bean>
使用JUtil进行测试,首先在类中创建函数
private ApplicationContext IOC = new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void Test() {}
类中获取有两种方式
/*
* 1.通过ID获取bean
* */
Object bean = IOC.getBean("book02");
System.out.println(bean);
/*
* 2.通过类类名获取bean,当有多个相同类的bean时会报错
* */
Book bean1 = IOC.getBean(Book.class);
System.out.println(bean1.getName()+":"+bean1.getAuthor());
2.获取bean的级联属性
<!--给bean的级联属性赋值 -->
<bean id="stuDao" class="com.neuedu.spring.entity.StudentDao"></bean>
<bean id="stuService" class="com.neuedu.spring.entity.StudentService">
<property name="dao" ref="stuDao"></property>
</bean>
<bean id="stuController" class="com.neuedu.spring.entity.StudentController">
<property name="service" ref="stuService"></property>
<property name="service.dao.username" value="testMan"></property>
</bean>
/*
* 获取bean的级联属性
* */
Object bean2 = IOC.getBean("stuController");
System.out.println(bean2);
StudentController bean2_2 = IOC.getBean(StudentController.class);
System.out.println(bean2_2.getService().getDao().getUsername());
3.通过p名称空间复制的bean
<!-- 通过p名称空间为bean赋值 -->
<bean id="book03" class="com.neuedu.spring.entity.Book"
p:name="白夜行"
p:author="东野圭吾"
p:price="51.0"
p:cbs="燕山大学出版社"
/>
/*
* 获取通过p名称空间赋值的bean
* */
Object bean3 = IOC.getBean("book03");
System.out.println(bean3);
4.
<!-- 测试bean的作用域,分别创建单实例和多实例
测试bean的创建时机
-->
<bean id="student01" scope="singleton" class="com.neuedu.spring.entity.Student"></bean>
<bean id="teacher01" scope="prototype" class="com.neuedu.spring.entity.Teacher"></bean>
/*
* 测试bean的作用域,分别创建单实例和多实例
* 测试bean的创建时机
* */
Object bean4 = IOC.getBean("teacher01");
Object bean4_2 = IOC.getBean("teacher01");
scope为singleton的单实例bean在注入IOC容器时就已创建,scope为prototype的多实例bean在获取时创建
5.
<!-- 创建带有生命周期方法的bean -->
<bean id="student02" scope="singleton" class="com.neuedu.spring.entity.Student" init-method="init" destroy-method="destroy"></bean>
/*
* 创建带有生命周期方法的bean对象
* */
ConfigurableApplicationContext cac=(ConfigurableApplicationContext) IOC;
Object bean = IOC.getBean("student02");
cac.close();
6.
<!-- bean之间的依赖关系 -->
<bean id="student03" class="com.neuedu.spring.entity.Student" depends-on="teacher03"></bean>
<bean id="teacher03" class="com.neuedu.spring.entity.Teacher"></bean>
若不设置依赖关系,则按顺序创建bean,若设置了depends-on,则遇到student03的创建时,先创建teacher03
7.
<!-- 通过继承实现bean之间的配置信息重用 -->
<bean id="student04" class="com.neuedu.spring.entity.Student">
<property name="name" value="st4"></property>
<property name="grade" value="2"></property>
<property name="address" value="天津"></property>
</bean>
<bean id="student05" class="com.neuedu.spring.entity.Student" parent="student04">
<property name="name" value="st5"></property>
</bean>
<!-- 通过abstract创建一个模板bean -->
<bean id="book04" class="com.neuedu.spring.entity.Book" abstract="true">
<property name="name" value="我是猫"></property>
<property name="author" value="夏目漱石"></property>
<property name="price" value="15.2"></property>
<property name="cbs" value="京都出版社"></property>
</bean>
<bean id="book05" class="com.neuedu.spring.entity.Book" parent="book04">
<property name="name" value="虞美人草"></property>
</bean>
abstract的bean不能被获取
9.
<!-- 测试使用NULL值 -->
<!-- NULL值等价于不设定value值, 基本数据类型不可使用NULL值 -->
<bean id="book06" class="com.neuedu.spring.entity.Book">
<property name="name" value="我是猫"></property>
<property name="author">
<null></null>
</property>
<property name="price" value="0.0"></property>
<property name="cbs" value="京都出版社"></property>
</bean>
10.
<!-- 引用外部bean -->
<bean id="bookShop01" class="com.neuedu.spring.entity.BookShop">
<property name="name" value="城市之光"></property>
<property name="book" ref="book06"></property>
</bean>
<!-- 引用内部bean -->
<bean id="bookShop02" class="com.neuedu.spring.entity.BookShop">
<property name="name" value="城市之光"></property>
<property name="book">
<bean class="com.neuedu.spring.entity.Book">
<property name="name" value="我是猫"></property>
<property name="author" value="夏目漱石"></property>
<property name="price" value="15.2"></property>
<property name="cbs" value="京都出版社"></property>
</bean>
</property>
</bean>
12.
<!-- 使用List类型的集合属性 -->
<bean id="bookShop03" class="com.neuedu.spring.entity.BookShop">
<property name="name" value="城市之光"></property>
<property name="book">
<bean class="com.neuedu.spring.entity.Book">
<property name="name" value="我是猫"></property>
<property name="author" value="夏目漱石"></property>
<property name="price" value="15.2"></property>
<property name="cbs" value="京都出版社"></property>
</bean>
</property>
<property name="bookList">
<list>
<ref bean="book01"/>
<ref bean="book02"/>
<ref bean="book03"/>
</list>
</property>
</bean>
/*
* 测试List类型的集合属性
* */
BookShop bean10 = (BookShop)IOC.getBean("bookShop03");
List<Book> bookList = bean10.getBookList();
for(Book book:bookList) {
System.out.println(book);
}
<!-- 使用Map类型的集合属性 -->
<bean id="bookShop04" class="com.neuedu.spring.entity.BookShop">
<property name="name" value="城市之光"></property>
<property name="bookMap">
<map>
<entry>
<key>
<value>book01</value>
</key>
<ref bean="book01"/>
</entry>
<entry>
<key>
<value>book02</value>
</key>
<ref bean="book02"/>
</entry>
<entry>
<key>
<value>book03</value>
</key>
<ref bean="book03"/>
</entry>
</map>
</property>
</bean>
/*
* 测试Map类型的集合属性
* */
BookShop bean11 = (BookShop)IOC.getBean("bookShop04");
Map<String, Book> bookMap = bean11.getBookMap();
Set<Entry<String,Book>> entrySet = bookMap.entrySet();
for (Entry<String, Book> entry : entrySet) {
System.out.println(entry);
}
14.
<!-- 使用prop子元素为Properties类型的属性值赋值 -->
<bean id="bookShop05" class="com.neuedu.spring.entity.BookShop">
<property name="name" value="城市之光"></property>
<property name="p">
<props>
<prop key="book01">value1</prop>
<prop key="book02">value2</prop>
<prop key="book03">value3</prop>
</props>
</property>
</bean>
/*
* 测试properties类型
* */
BookShop bean11 = (BookShop)IOC.getBean("bookShop05");
Properties p = bean11.getP();
System.out.println(p);
5.通过工厂创建bean
1.静态工厂
调用静态工厂方法创建bean是将对象创建的过程封装到静态方法中。当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节。
声明通过静态方法创建的bean需要在bean的class属性里指定静态工厂类的全类名,同时在factory-method属性里指定工厂方法的名称。最后使用<constrctor-arg>元素为该方法传递方法参数。
*Book为一个{String bookName,String author,double price}的对象
import java.util.HashMap;
import java.util.Map;
/*
* 所谓的静态工厂实例 是指:工厂类本身不用创建对象,而是通过其提供的静态方法来获取一个对象
* 创建对象:
* 1.往内存中【JVM】加载类的字节码文件
* 2.根据类的字节码文件创建一个对象
* */
public class staticFactory {
private static Map<String, Book> bookList=null;
static {
bookList=new HashMap<String, Book>();
bookList.put("book01", new Book("人间失格", "太宰治", 25.0));
bookList.put("book02", new Book("嫌疑人X的献身", "东野圭吾", 15.6));
bookList.put("book03", new Book("罗生门", "芥川龙之介", 18.1));
}
public static Book getBookByID(String id) {
return bookList.get(id);
}
}
<!-- 配置静态工厂 -->
<bean id="staticFactory" class="com.neuedu.factory.staticFactory" factory-method="getBookByID">
<constructor-arg value="book01"></constructor-arg>
</bean>
2.实例工厂
实例工厂方法:将对象的创建过程封装到另外一个对象实例的方法里。当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节。
实现方式
①配置工厂类实例的bean
②在factory-method属性里指定该工厂方法的名称
③使用construtor-arg 元素为工厂方法传递方法参数
import java.util.HashMap;
import java.util.Map;
/*
* 实例工厂先创建一个工厂对象,然后在通过工厂对象的方法获取一个实例!
* */
public class instanceFactory {
private Map<String, Book> bookList=null;
{
bookList=new HashMap<String, Book>();
bookList.put("book01", new Book("人间失格", "太宰治", 25.0));
bookList.put("book02", new Book("嫌疑人X的献身", "东野圭吾", 15.6));
bookList.put("book03", new Book("罗生门", "芥川龙之介", 18.1));
}
public Book getBookByID(String id) {
return bookList.get(id);
}
}
<!-- 配置实例工厂 -->
<bean id="instanceFactory" class="com.neuedu.factory.instanceFactory"/>
<bean id="bookFromInstanceFactory" factory-bean="instanceFactory" factory-method="getBookByID">
<constructor-arg value="book01"></constructor-arg>
</bean>
Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,即FactoryBean。
工厂bean跟普通bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂bean的getObject方法所返回的对象。
工厂bean必须实现org.springframework.beans.factory.FactoryBean接口。
public class factoryBean implements FactoryBean<Book>{
@Override
public Book getObject() throws Exception {
// Spring的IOC容器就是通过调用的该方法返回对象的
return new Book("罗生门", "芥川龙之介", 18.1);
}
@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return Book.class;
}
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return true;
}
}
<!-- 配置工厂bean -->
<bean id="factoryBean" class="com.neuedu.factory.factoryBean"></bean>
6.bean的后置处理器
1.在bean的初始化方法调用前后执行操作的专门的对象
2.自定义后置处理器实现该接口:org.springframework.beans.factory.config.BeanPostProcessor
3.在springmvc中配置一下该bean对象.
实现BeanPostProcessor
/*
* 需要实现BeanPostProcessor接口,在bean初始化前后进行调用
* */
public class postProcess implements BeanPostProcessor{
/*
* 参数列表:
* 1.Object bean对象
* 2.String bean的name
* */
@Override
public Object postProcessAfterInitialization(Object objectName, String beanID) throws BeansException {
// 在bean初始化之后进行调用
System.out.println("postProcessAfterInitialization:"+objectName+"-"+beanID);
return objectName;
}
@Override
public Object postProcessBeforeInitialization(Object objectName, String beanID) throws BeansException {
// 在bean初始化之前进行调用
System.out.println("postProcessBeforeInitialization:"+objectName+"-"+beanID);
return objectName;
}
}
在javaBean中加入init方法,并在bean的配置中添加init-method
测试可得,postProcessBeforeInitialization和postProcessAfterInitialization分别在init方法也就是bean初始化的前后,若没有bean则不会有postProcessAfterInitialization方法的执行