1. Spring IOC
1.1 概述
- 把实体的创建权交给Spring,以便解耦,Spring使用配置文件+实例工厂+反射创建实例
1.2 配置文件applicationContext.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">
<!-- id:实例的名称,可以被配置文件和Spring创建实例时引用 -->
<!-- class:被实例化的类完整路径 -->
<!-- scope:实例的作用范围
singleton:单例,该类只会创建一次对象,默认值(常用)
prototype:多例,每次从容器中获取Bean时,都会创建一个新的实例,Acition实例化需要多例(常用)
request:用于Web应用环境,针对每次HTTP请求都会创建一个实例
session:用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例
global session:仅在Portlet的Web应用中使用,同一个全局会话共享一个实例,对于非Portlet环境,等同于session
-->
<bean id="student" class="com.domain.Student" scope="singleton"></bean>
<!-- 在一个配置文件中引入多个配置文件(配置文件拆分) -->
<import resource="/applicationContext2.xml"/>
</beans>
1.3 从Spring容器中获取实例
//读取spring配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext("/applicationContext.xml");
//根据bean标签的id属性值查找实例
Student student= ac.getBean("student",Student.class);
//操作实例对象
System.out.println(student.toString());
2. 依赖注入
2.1 构造方法注入属性值
<bean id="student" class="com.domain.Student">
<!-- Student类中定义了构造方法Student(Integer id, String name) -->
<!-- constructor-arg表示构造方法的参数,name表示参数名称,value表示参数值 -->
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="张三"></constructor-arg>
</bean>
2.2 setter方法注入属性值
<bean id="grade" class="com.domain.Grade">
<!-- property标签表示一个属性,name表示属性名,value表示要注入的属性值 -->
<property name="id" value="1"></property>
<property name="name" value="高一(1)班"></property>
</bean>
<bean id="student" class="com.domain.Student">
<!-- ref可以注入对象类型的数据,ref的值对应上面id为grade的bean -->
<property name="grade" ref="grade"></property>
</bean>
2.3 p命名空间注入属性值
- Spring2.5后才能使用p命名空间
- 需要在beans标签下引入p命名空间规范
xmlns:p="http://www.springframework.org/schema/p"
<!-- 直接在bean标签的属性中使用p命名空间为对的属性赋值 -->
<!-- 基本类型格式:【p:对象属性名="值"】 -->
<!-- 对象引用格式:【P:对象属性名-ref="值"】 -->
<bean id="grade" class="com.domain.Grade" p:id="2" p:name="高一(4)班"></bean>
<bean id="student" class="com.domain.Student" p:grade-ref="grade"></bean>
2.4 SpEL注入属性值
- Spring3后才能使用SpEL
- SpEL能执行java代码(跟EL表达式类似)
<bean id="grade" class="com.domain.Grade">
<!-- SpEL表达式格式: #{值} 值为字符串需要加单引号 -->
<property name="id" value="#{3}"></property>
<property name="name" value="#{'高三(3)班'}"></property>
</bean>
<bean id="student" class="com.domain.Student">
<!-- 无论值是否为对象类型,直接用value即可,SpEL会自动解析值类型 -->
<property name="grade" value="#{grade}"></property>
<!-- SpEL可以执行java代码 -->
<property name="name" value="#{grade.getName()+'的学生'}"></property>
</bean>
2.5 自动装配autowire
- 2.5.1 自动装配autowire属性值
-
byName
- 根据属性名自动装配,
- BeanFactory查找id与属性的setter方法匹配的Bean,找到即自动注入,否则什么都不做
-
byType 根据属性类型自动装配
- 如果正好有一个与依赖属性类型相同的Bean,就自动装配这个属性
- 如果有多个这样的的Bean,Spring无法决定哪个Bean,就抛出一个致命异常
- 如果没有匹配的Bean,就什么都不做,属性不会被设置
-
no
- 不使用自动装配
-
constructor
- 跟byType差不多,它是应用于构造注入自动装配
- 如果在容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常
-
<bean id="userDao" class="com.dao.impl.UserDaoImpl" ></bean>
<bean id="productDao" class="com.dao.impl.ProductDaoImpl"></bean>
<!-- ShoppingCarServiceImpl中需要用到userDao和productDao,autowire能自动给这两个属性值(需要setter方法)自动装配赋值 -->
<bean id="shoppingCarService" class="com.service.impl.ShoppingCarServiceImpl" autowire="byName"></bean>
- 全局自动装配
- Spring配置文件设置了default-autowire后当前文件的bean都会默认自动装配,如果是拆分多个配置文件,只有设置了default-autowire的配置文件才生效,其他配置文件不生效
<!-- 在Spring配置文件开头的<beans>文件中添加default-autowire="自动装配值" -->
<beans default-autowire="byName" >
2.6 注入不同类型的数据(了解)
-
注入基本类型(字符串和其他基本类型)
- 看上面例子
-
引用bean实例
- 看上面例子
-
使用内部Bean
<bean id="userBiz" class="com.biz.impl.UserBizImpl">
<property name="userDao">
<!-- 内部bean直接使用class属性,不用id属性,不能被其他bean调用 -->
<bean class="com.dao.impl.UserDaoImpl"></bean>
</property>
</bean>
- 注入List集合或数组类型的属性值
<bean id="user" class="com.entity.User">
<property name="hobbies">
<!-- list标签注入List集合或数组的多个值 -->
<list>
<value>篮球</value>
<value>足球</value>
<value>乒乓球</value>
</list>
</property>
</bean>
- 注入Set集合的属性值
<bean id="user" class="com.entity.User">
<property name="hobbies">
<!-- set标签注入Set集合 -->
<set>
<value>篮球</value>
<value>足球</value>
<value>乒乓球</value>
</set>
</property>
</bean>
- 注入Map集合的属性值
<bean id="user" class="com.entity.User">
<property name="hobbies">
<!-- map标签注入Map集合多个键值对 -->
<map>
<!-- 一个entry标签表示一个键值对 -->
<entry>
<!-- entry标签的子key标签表示Map集合的key,key标签包含的value表示key值 -->
<key><value>basketball</value></key>
<!-- entry标签的子value标签表示Map集合的value -->
<value>篮球</value>
</entry>
<entry>
<key><value>football</value></key>
<value>足球</value>
</entry>
</map>
</property>
</bean>
- 注入Properties类型的属性值
<bean id="user" class="com.entity.User">
<property name="hobbies">
<!-- props标签注入Properties集合多个键值对 -->
<props>
<!-- 一个prop标签表示一个键值对 -->
<!-- key属性表示key值 -->
<!-- prop标签包含的文本是value值 -->
<prop key="backetball">篮球</prop>
<prop key="football">足球</prop>
</props>
</property>
</bean>
- 注入null和空字符串值
<!-- value标签中间不填东西就是空字符串 -->
<property name="a"><value></value></property>
<!-- null标签表示null值 -->
<property name="b"><null/></property>
3. 使用注解方式依赖注入
3.1 修改配置文件
- 标签多了个xmlns:context项,xsi:schemaLocation的值多了2个
- 设置扫描注解类的包
- default-autowire设置和context:component-scan是在同一个配置文件,则会对类的对象属性进行自动装配(对象属性需要要setter方法,不需要在对象属性上添加注解)
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 注解组件扫描,base-package表示要扫描的包,多个包用逗号隔开 -->
<context:component-scan base-package="com.service.impl,com.dao.impl"></context:component-scan>
</beans>
3.2 常用注解
- 3.2.1 注解定义bean
@Repository("bean id")
用于标注Dao的实现类
@Repository("productDao")
public class ProductDaoImpl implements ProductDao {}
@Service("bean id")
用于标注Service实现类
@Service("shoppingCarService")
public class ShoppingCarServiceImpl implements ShoppingCarService {}
@Controller("bean id")
用于标注控制器类@Component("bean id")
用于标注通用bean的类
- 3.2.2 自动装配注解
- 注解自动装配不用setter方法,直接在属性上面添加注解即可
@Autowired
根据类型进行自动装配@Qualifier("bean id")
与@Autowired结合一起使用就变成根据名字进行自动装配@Resource(name="bean id")
根据名字进行自动装配,等同于上面两个结合
//@Autowired与@Qualifier结合一起就是按名字自动装配
@Autowired
@Qualifier("userDao")
private UserDao userDao;
//根据名字进行自动装配
@Resource(name="productDao")
private ProductDao productDao;
- 3.2.3 基本类型数据注解
@Value("我是注解方式的属性值")
private String message;
- 3.2.4 bean作用域注解
@Scope("作用域")
在类上面注解作用范围,作用域的值参考2.5