目录
- 1.基础
- 2.IOC基于xml的配置
- 3.IOC基于注解的配置
- 4.AOP的相关概念
- 6.spring进阶
- 7.消息监听机制
- 8.事物控制与传播行为
- 9.Spring源码
- 10.spring的生命周期
1.application.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<!--beans中添加了许多约束,即像url一样的代码,其作用就是约束该.xml文件中可以使用哪些标签-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
<!--开启注解扫描-->
<context:component-scan base-package="com.qunar.事物"></context:component-scan>
<!--注册user类-->
<bean name="user" class="com.qunar.spring入门.pojo.User"></bean>
<!--把数据库的配置信息写在一个独立的文件中,编译修改数据库的配置内容
让spring知道jdbc.properties文件的位置
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--声明数据源DataSource,作用是连接数据库-->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--set注入提供连接数据库信息-->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${jdbc.maxActive}" />
</bean>
<!--SqlSessionFactory-->
<!--声明的是mybatis中提供的SqlSessionFactoryBean类,这个类内部创建SqlSessionFactory-->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池付给dataSource属性-->
<property name="dataSource" ref="myDataSource"/>
<!--mybatis主配置文件的位置
configLocation属性是Resource类型,读取配置文件
它的赋值使用的是value , 指定文件的路径,使用的是classpath:表示文件的位置
-->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<!--创建 dao对象
使用SqlSession的getMapper(StudentDao.class)
MapperScannerConfigurer在内部调用getMapper()生成每个dao接口的代理对象
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定的是SqlSessionFactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="SqlSessionFactory"/>
<!--指定包名,包名是dao接口所在的包名
MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
一次getMapper()方法,得到每个接口的dao对象
创建好的dao对象放入到spring的容器中
dao默认对象的名称:是接口名字的首字母小写
-->
<property name="basePackage" value="com.qunar"/>
<!--多个包-->
<!--<property name="basePackage" value="com.md.dao,com.md.dao2"/>-->
</bean>
</beans>
2.bean标签
(1)作用:配置对象让spring来创建
默认情况使用无参构造函数创建对象,没有无参构造函数则创建不成功
(2)属性:
id:给对象在容器中提供一个唯一标识。用于获取对象。
class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
scope:指定对象的作用范围。
- singleton :默认值,单例的.
- prototype :多例的.
- request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
- session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
- global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么globalSession 相当于 session. init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
3.实例化bean的两种方式
第一种方式:使用默认无参构造函数
<!--在默认情况下:
它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"/>
第二种方式:使用工厂类的静态方法
/**
* 模拟一个静态工厂,创建业务层实现类
*/
public class StaticFactory {
public static IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此种方式是:
使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
id 属性:指定 bean 的 id,用于从容器中获取
class 属性:指定静态工厂的全限定类名
factory-method 属性:指定生产对象的静态方法
-->
<bean id="accountService"
class="com.itheima.factory.StaticFactory"
factory-method="createAccountService"></bean>
第三种方式:使用实例对象的方法
/**
* 模拟一个实例工厂,创建业务层实现类
* 此工厂创建对象,必须现有工厂实例对象,再调用方法
*/
public class InstanceFactory {
public IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此种方式是:
先把工厂的创建交给 spring 来管理。
然后在使用工厂的 bean 来调用里面的方法
factory-bean 属性:用于指定实例工厂 bean 的 id。
factory-method 属性:用于指定实例工厂中创建对象的方法。
-->
<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService"
factory-bean="instancFactory"
factory-method="createAccountService"></bean>
4.spring依赖注入
给spring容器中的bean对象属性注入初始值
第一种方式:使用构造函数注入
<!-- 使用构造函数的方式,给 service 中的属性传值
要求:
类中需要提供一个对应参数列表的构造函数。
涉及的标签:
constructor-arg
属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称
=======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<constructor-arg name="name" value=" 张三 "></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
第二种方式:使用set方法注入
<!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:
property
属性:
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的
实际开发中,此种方式用的较多。
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="name" value="test"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
5.集合的注入
<!-- 注入集合数据
List 结构的:
array,list,set
Map 结构的
map,entry,props,prop
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
<!-- 给数组注入数据 -->
<property name="myStrs">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 注入 list 集合数据 -->
<property name="myList">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<!-- 注入 set 集合数据 -->
<property name="mySet">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!-- 注入 Map 数据 -->
<property name="myMap">
<props>
<prop key="testA">aaa</prop>
<prop key="testB">bbb</prop>
</props>
</property>
<!-- 注入 properties 数据 -->
<property name="myProps">
<map>
<entry key="testA" value="aaa"></entry>
<entry key="testB"><value>bbb</value></entry>
</map>
</property>
</bean>
6.lookup-method与replace-method
Spring的方法注入可分为两种
查找方法注入:用于注入方法返回结果,也就是说能通过配置方式替换方法返回结果。即我们通常所说的lookup-method注入。
替换方法注入:可以实现方法主体或返回结果的替换,即我们通常所说的replaced-method注入。
(一)lookup-method
(1)当单例对象依赖多例对象时,保证获得的多例对象不会存储在spring容器中,每个单例对象持有的多例对象是独立的
(2)对方法的返回结果进行增强
public class Car {
//用于lookup-method注入
public Taxi createTaxi(){
System.out.println("car");
Taxi taxi = new Taxi();
taxi.setTaxiNmae("carCreate");
return taxi;
}
private Taxi taxi;
public Taxi getTaxi() {
return taxi;
}
//setter注入
public void setTaxi(Taxi taxi) {
this.taxi = taxi;
}
}
public class Taxi {
private String taxiNmae;
public void setTaxiNmae(String taxiNmae) {
this.taxiNmae = taxiNmae;
}
public void say() {
System.out.println("I am a Taxi..."+taxiNmae);
}
}
public class lookupMethod与replaceMethod {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("lookupMethodAndRelapceMethod.xml");
Car car1 = (Car) applicationContext.getBean("car");
Car car2 = (Car) applicationContext.getBean("car");
System.out.println("Car:singleton,所以car1==car2应该为" + (car1 == car2));
Taxi taxi1 = car1.getTaxi();
Taxi taxi2 = car1.getTaxi();
System.out.println("Taxi:prototype,Car:singleton,未使用lookup-method注入所以taix1==taxi2应该为" + (taxi1 == taxi2));
Taxi taxi3 = car1.createTaxi();
Taxi taxi4 = car1.createTaxi();
System.out.println("Taxi:prototype,Car:singleton,使用lookup-method注入所以taix3==taxi4应该为" + (taxi3 == taxi4));
taxi1.say();
taxi3.say();
}
}
<bean id="taxi" class="com.qunar.spring入门.pojo.Taxi" scope="prototype"></bean>
<bean id="car" class="com.qunar.spring入门.pojo.Car">
<property name="taxi" ref="taxi"></property>
<lookup-method name="createTaxi" bean="taxi" ></lookup-method>
</bean>
输出结果
Car:singleton,所以car1==car2应该为true
Taxi:prototype,Car:singleton,未使用lookup-method注入所以taix1==taxi2应该为true
Taxi:prototype,Car:singleton,使用lookup-method注入所以taix3==taxi4应该为false
I am a Taxi...null
I am a Taxi...null
(二)replace-method
替换方法体及其返回值
注意,增强的方法必须实现MethodReplacer接口
public class OriginalDog {
public void sayHello() {
System.out.println("Hello,I am a black dog...");
}
public void sayHello(String name) {
System.out.println("Hello,I am a black dog, my name is " + name);
}
}
public class ReplaceDog implements MethodReplacer {
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("Hello, I am a white dog...");
Arrays.stream(args).forEach(str -> System.out.println("参数:" + str));
return obj;
}
}
public class lookupMethod与replaceMethod {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("lookupMethodAndRelapceMethod.xml");
System.out.println("++++++++++++++++++++++++++++++++++++++++++");
OriginalDog originalDog = (OriginalDog) applicationContext.getBean("originalDog");
originalDog.sayHello("sssss");
}
}
<!-- ====================replace-method属性注入==================== -->
<bean id="replaceDog" class="com.qunar.spring入门.pojo.ReplaceDog"></bean>
<bean id="originalDog" class="com.qunar.spring入门.pojo.OriginalDog">
<replaced-method name="sayHello" replacer="replaceDog">
<arg-type match="java.lang.String"></arg-type>
</replaced-method>
</bean>
输出结果
Hello, I am a white dog...
参数:sssss
7.spring引入多个配置文件
(1)通过<import>
标签引入其他的配置文件
<import resource="配置文件2.xml"></import>
<bean id="user" class="com.qunar.spring入门.pojo.User"></bean>
(2)直接在ApplictionContext中传入多个配置文件
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("配置文件1.xml","配置文件2.xml");