Spring(笔记2)
IOC容器
1、IOC的概念跟原理
a. 概念:
控制反转,把对象的创建与对象之间的调用交给spring管理,使用IOC目的是为了降低耦合度
b. IOC底层原理
Xml解析,工厂模式,反射
原始方式 new 耦合度太高
工厂模式解耦合(非最终方案):
创建一个工厂类,添加方法返回所需要的对象(工厂方法中去new对象)
IOC解耦过程:
IOC解耦是将耦合度降到最低限度
2、IOC接口
a. IOC思想是基于IOC容器去完成的,IOC容器底层就是对象的工厂
b. 要对工厂进行实例化,Spring提供了IOC的两种实现方式:
BeanFactory
ApplicationContext
相同点:
他们都能实现加载配置文件,通过工厂过程去创建对象
不同点:
BeanFactory是spring的内部使用接口,一般不提供给开发人员使用,加载配置文件时不会创建对象,获取对象或使用对象时才会创建对象
ApplicationContext是BeanFactory的子接口,一般开发人员使用,加载配置文件时就会将配置文件中的对象创建
C.实现类
ApplicationContext:
ClassPathXmlApplicationContext:编译后的路径(src下的路径)
FileSystemXmlApplicationContex:对应的是盘全路径(E:\MyEclipse_WordSpace\FirstSpring\src)
BeanFactory:ApplicationContext
3、IOC操作(bean管理操作)
a.bean管理:
spring创建对象
spring注入属性
b.bean管理有两种方式:
基于xml配置方式
基于注解方式
4、IOC操作bean管理(基于xml方式)
a.基于xml创建对象
id:给对象取一个唯一标识(不是创建对象的名字)
class:创建类的全路径(包类的路径)
name:作用与id相同,(id不能加特殊符号,name可以加特殊符号)
b.基于xml方式注入属性(注入属性要在创建对象的基础上进行)
DI:依赖注入,注入属性(DI是IOC的一种具体实现)
c.第一种注入方式:set方法注入
创建类,定义属性和对应的set方法
在配置文件中配置bean,并且配置属性
d.第二种注入方式:有参构造注入
创建类、属性、有参构造
在spring配置文件中进行配置
e. p名称空间(了解)
添加p名称空间约束
xmlns:p=http://www.springframework.org/schema/p
进行属性注入
5.IOC操作bean管理(xml注入其他类属性)
a.字面量(向一个类中设置属性固定值)(创建属性时直接赋值、标签赋值)
赋值null值
设置属性值中包含特殊符号<>:把带特殊符号的内容写到CDATA中
b.注入属性——外部bean
Service中调用dao
//创建PersonDao类型属性。生成set方法
private PersonDao personDao;
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
c.注入属性——内部bean
一对多关系:部门与员工(一个部门有多个员工,每个员工都有所属部门)
在实体类中表示一对多关系
在spring配置文件中进行配置
d.注入属性——级联赋值
第一种写法:
第二种写法:
6、IOC操作bean管理-xml注入集合属性
1) 创建类,定义数组、list、map、set类型的属性,并生成set()
2) 在spring配置文件中配置
3) 在集合中设置对象属性值
<!-- 注入集合类型属性 -->
<bean id="stu2" class="com.spring.domain.Student1">
<!-- 数组类型属性注入 -->
<property name="courses">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</property>
<!-- list集合属性注入 -->
<property name="lists">
<list>
<value>aaaa</value>
<value>bbbb</value>
<value>cccc</value>
</list>
</property>
<!-- map集合属性注入 -->
<property name="maps">
<map>
<entry key="k1" value="value1"></entry>
<entry key="k2" value="value2"></entry>
</map>
</property>
<!-- set集合属性注入 -->
<property name="sets">
<set>
<value>s1</value>
<value>s2</value>
<value>s3</value>
</set>
</property>
<!-- list对象集合属性注入 -->
<property name="courseList">
<list>
<ref bean="course1"/>
<ref bean="course2"/>
</list>
</property>
</bean>
<bean id="course1" class="com.spring.domain.Course">
<property name="cname" value="java"></property>
<property name="time" value="6"></property>
<property name="teacher" ref="teacher1"></property>
</bean>
<bean id="course2" class="com.spring.domain.Course">
<property name="cname" value="mysql"></property>
<property name="time" value="7"></property>
<property name="teacher" ref="teacher1"></property>
</bean>
4) 把集合注入的部门提取出来
a. 在spring配置文件中引入名称空间util
xmlns:util=http://www.springframework.org/schema/util
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util.xsd
"
b) 使用util标签完成list集合注入提取
<bean id="stu3" class="com.spring.domain.Student2">
<property name="lists" ref="list1"></property>
</bean>
<util:list id="list1">
<value>aaaa</value>
<value>bbbb</value>
<value>cccc</value>
</util:list>
7、IOC操作bean管理-FactoryBean
1). spring中有两种bean,一种普通的bean(我们自己建的bean),还有工厂bean(FactoryBean)
2). 普通bean(定义什么类型,返回什么类型)
在spring配置文件中定义的bean类型就是返回类型
3). 工厂bean:在spring中配置类型可以和返回类型不一样
a.创建类,让这个类作为工厂bean,实现FactoryBean接口
public class MyBean implements FactoryBean<Student1> {
//定义返回的bean
public Student1 getObject() throws Exception {
List<String> list = new ArrayList<String>();
list.add("1111");
list.add("2222");
list.add("333");
//设置MyBean返回对象是stu1
Student1 stu = new Student1();
stu.setLists(list);
return stu;
}
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return null;
}
public boolean isSingleton() {
// TODO Auto-generated method stub
return false;
}
}
<bean id="stu3" class="com.spring.factorybean.MyBean"></bean>
8、IOC操作bean管理-bean的作用域
1). Spring配置文件bean标签创建bean可以是一个单实例,也可以是一个多实例,默认单例(单实例每次只有一个对象,多实例每次都创建一个新的对象),Spring中可以去配置单实例还是多实例
2). 设置单例还是多例
scope属性设置
singleton 单实例(默认)
prototype 多实例
request、session
3). singleton和prototype 区别
a.一个实例,一个是多实例
b.设置为singleton时,加载配置文件时就会创建单实例对象,设置为prototype时,在调用getBean方法时创建多实例对象
9、IOC操作bean管理-bean生命周期
1)从对象创建到销毁的过程
2)bean生命周期
a.第一步,通过构造器创建bean实例
b.第二步,为bean属性设置值和对其他bean的引用
c.第三步,调用bean的初始化方法(需要进行配置)
d.第四步,bean使用
e.第五步,调用bean的销毁方法(需要进行配置)
3)演示bean生命周期
4)生命周期补充
Bean的后置处理器
初始化前:把bean实例传递给bean后置处理器的方法
初始化后:把bean实例传递给bean后置处理器的方法、
5) 演示添加后置处理器
a. 创建类,实现BeanPostProcessor接口
b. 配置后置处理器
public class MyBeanPost implements BeanPostProcessor {
//初始化之后
public Object postProcessAfterInitialization(Object bean, String arg1)
throws BeansException {
System.out.println("初始化之后执行");
return bean;
}
//初始化之前
public Object postProcessBeforeInitialization(Object bean, String arg1)
throws BeansException {
System.out.println("初始化之前执行");
return bean;
}
}
<!-- 配置后置处理器 -->
<bean id="myBeanPost" class="com.spring.processor.MyBeanPost"></bean>
10、IOC-操作bean-xml自动装配
1)自动装配
这种是手动装配置
自动装配:根据指定装配规则(属性名称,或者是属性类型),spring自动将匹配的属性值进行注入(不需要标签注入)
2)演示自动装配
原始方式:
<bean id="emp" class="com.spring.autowire.Emp">
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.spring.autowire.Dept"></bean>
自动装配:
byName:根据属性名称去装配,注入值bean的id值要和类属性名称一致
<bean id="emp" class="com.spring.autowire.Emp" autowire="byName"></bean>
<bean id="dept1" class="com.spring.autowire.Dept"></bean>
byType:根据属性类型装配,注入bean的类型要和类属性类型一致
<bean id="emp" class="com.spring.autowire.Emp" autowire="byType"></bean>
<bean id="dept1" class="com.spring.autowire.Dept"></bean>
注:byType中有两个Dept类的bean,spring根据类型找到了两个bean,无法确认要注入哪个bean,会报错,相同类型的bean只能定义一个
11、IOC-操作bean管理-基于注解方式
1)注解:
a.注解是代码里的一种特殊标记,
格式:
@注解名称(属性名=属性值)
@注解名称(属性名1=属性值1,属性名2=属性值2)
@注解名称
单元测试@Test注解
b.注解的作用范围:注解可以作用在类上面、方法上、属性上
c.注解的目的:简化xml配置
2)有哪些注解
Spring针对bean管理中创建对象提供以下注解:
@Component(普通对象)
@Service(业务逻辑层或service层)
@Controller(web层)
@Reponsitory(dao层或者持久层)
上面四个注解功能是一样的,都可以创建对象
3)基于注解方式创建对象
a)导入依赖 aop.jar
b)开启组件扫描
告诉spring要在哪个类上加注解,让spring扫描哪个类
引入context名称空间
<context:component-scan base-package=“com.spring.*”></context:component-scan>
base-package:告诉spring要扫描的包,多个包用逗号隔开
b) 创建类,添加创建对象的注解
@Component(value="userService")
public class UserService {
public void add() {
System.out.println();
}
}
此处的value就等价于xml配置bean标签的id,也就是创建对象的标识
Value属性值可以不写,如果不写默认类名称首字母小写
@Component//<bean id="userService" class="">
public class UserService {
public void add() {
System.out.println();
}
}
4)开启组件扫描其他
<!-- use-default-filters不写,spring例有一个默认的filter去找到包中所有类去扫码 -->
<!-- use-default-filters="false":不使用默认filter,使用自己配置的filter -->
<context:component-scan base-package="com.spring.*" use-default-filters="false">
<!-- context:include-filter:设置扫描哪些内容 -->
<!-- 到base-package包中只扫描带@Controller的注解-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:component-scan base-package="com.spring.*">
<!-- 设置哪些内容不进行扫描@Controller -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
5)基于注解实现属性注入
针对对象类型:
@AutoWired 根据属性类型自动注入
@Qualifier 根据属性名称注入
@Resource 既可以根据类型注入,也可以根据属性注入
针对普通类型:
@Value 注入是一个普通类型
a.@AutoWired(属性类型) ,找到要注入的属性接口的实现类注入
创建service和dao对象;
在service中注入dao对象,在service类中添加dao类型的属性,不要添加set方法
@Component
public class UserService {
//根据属性类型注入
@Autowired
private UserDao userDao;
public void add() {
System.out.println("service");
userDao.update();
}
}
public interface UserDao {
public void update();
}
@Repository
public class UserDaoImpl implements UserDao {
public void update() {
System.out.println("update");
}
}
b.@Qualifier根据属性名称注入
当一个接口有多个实现类,spring不知道要注入哪个实现类
与@Autowird一起使用
@Autowired
@Qualifier(value="userDaoImpl")
private UserDao userDao;
c)@Resource既可以感觉类型注入,也可以根据名称注入
@Resource//根据类型
@Resource(name="userDaoImpl")//根据属性名称注入
private UserDao userDao;
d.@Value
@Value(value="zhangsan")
private String name ;
6) 完全注解开发(springboot)
a. 创建配置类,替代xml配置文件
//作为配置类
@Configuration
//代表开启组件扫描
@ComponentScan(basePackages={"com.spring.*"})
public class SpringConfig {
}
b. 编写测试类
@Test
public void testAutowire(){
//加载配置类
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
//获取创建对象
UserService service = context.getBean("userService",UserService.class);
service.add();
}
7)注解配置bean作用域
@Scope(value="singleton")
Singleton:配置单例
Prototype:配置多例