1 IOC 和 和 DI
-
IOC 反转控制:
在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需
要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式,
增加了学习成本,同时降低了开发效率。
反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取
方向——改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创
建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发
的效率。这种行为也称为查找的被动形式 -
DI 依赖注入:
IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如:setter 方法)接受
来自于容器的资源注入。相对于 IOC 而言,这种表述更直接。 -
IOC实现:
-
BeanFactory:IOC容器的基本实现,是Spring内部接口,不提供开发人员使用
加载配置文件时不创建对象
-
ApplicationContext:BeanFactory的子接口,功能更强大,开发人员用
加载配置文件时就会把在配置文件对象进行创建
-
-
ApplicationContext实现类:
- ClassPathXmlApplicationContext:对应类路径下的 XML 格式的配置文件
- FileSystemXmlApplicationContext:对应文件系统中的 XML 格式的配置文件
2 IOC操作Bean管理(基于xml方式)
-
创建bean对象
<bean id="user" class = "com.atguigu.spring5.User"></bean> /* 从 IOC 容器中获取 bean 时,除了通过 id 值获取,还可以通过 bean 的类型获取。但如 果同一个类型的 bean 在 XML 文件中配置了多个,则获取时会抛出异常,所以同一个类 型的 bean 在容器中必须是唯一的。 */ BeanFactory cxt = new ClassPathXmlApplicationContext("bean.xml"); HelloWorld helloWorld = cxt.getBean(HelloWorld. class); /* 或者可以使用另外一个重载的方法,同时指定 bean 的 id 值和类型 */ HelloWorld helloWorld = cxt.getBean(“helloWorld”,HelloWorld. class);
-
常用的bean属性
- id:唯一标识
- class:类全路径
-
基于set方法注入属性
//使用有参数的property标签 <bean id="user" class = "com.atguigu.spring5.User"> <property name="bname" value="xxx"></property> </bean>
-
基于有参构造注入属性
<bean id="order" class="com.atguigu.spring5.Order"> <constructor-arg name="name" value="amazing"></constructor-arg> <constructor-arg name="address" value="yongling"></constructor-arg> <!-- <constructor-arg index="0" value="123"></constructor-arg> index指的是有参构造中的第i个参数--> </bean>
-
p名称空间注入
可以简化基于xml配置方式
(1)添加p名称空间在配置文件中 xmlns:p="http://www.springframework.org/schema/p" (2)进行属性注入,在bean标签里面进行操作 <bean id="user" class = "com.atguigu.spring5.User" p:bname="amazingaaaaa">
-
使用xml注入特殊的值
空值: <property name="address" > <null></null> </property> 含有特殊符号: (1) 转义字符 (2) 写入CDATA中 <property name="address" > <value><![CDATA[<<nanjing>>]]></value> </property>
-
注入外部bean
正常不使用spring的方法:
- 创建两个类service与dao
- 在service中调用dao的方法
使用spring:
<!--法一 外部bean,使用引用ref,推荐:--> <bean id = "userService" class="com.atguigu.spring5.service.UserService"> <property name="userDao" ref="userDaoImpl"></property><!--ref作为引用指向外部的userDaoImpl--> </bean> <bean id = "userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"> </bean> <!--法二 内部bean,代码可复用率低,不推荐:--> <bean id="emp" class="com.atguigu.spring5.bean.Emp"> <property name="name" value="ikun"></property> <property name="gender" value="?"></property> <property name="dept"> <bean id="dept" class="com.atguigu.spring5.bean.Dept"> <property name="name" value="实习"></property> </bean> </property> </bean>
-
xml注入集合属性
<bean id="stu" class="com.atguigu.spring5.collectionType.Student"> <!--数组--> <property name="course"> <array> <value>java</value> <value>python</value> </array> </property> <!--列表--> <property name="list"> <array> <value>c++</value> <value>c#</value> </array> </property> <!--map(注意有两个属性 key value)--> <property name="maps"> <map> <entry key="JAVA" value="java"></entry> <entry key="PYTHON" value="python"></entry> </map> </property> <!--集合--> <property name="sets"> <set> <value>Mysql</value> <value>Redis</value> </set> </property> <!--集合的内部属性为一个类时,方式类似上文的引用,将ref参数单独--> <property name="courses"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean> <bean id="course1" class="com.atguigu.spring5.collectionType.Course"> <property name="name" value="spring5"></property> </bean> <bean id="course2" class="com.atguigu.spring5.collectionType.Course"> <property name="name" value="mybatis"></property> </bean>
-
将集合注入部分提取出来
-
在spring配置文件中配置命名空间util
<beansxmlns: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 http://www.springframework.org/schema/util/spring-util.xsd">></beans> <!--首先引用util的名称空间,然后再在xsi:schemaLocation给出URI引用对,第一个URI是名称空间的名字,第二个URI给出模式文档的位置,模式处理器将从这个位置读取模式文档,该模式文档的目标名称空间必须与第一个URI相匹配-->
-
使用util标签
<util:list id="mlists"> <value>数值计算</value> <value>数据分析</value> </util:list> <bean id="book" class="com.atguigu.spring5.collectionType.Book"> <property name="lists" ref="mlists"></property> </bean>
-
3 IOC操作Bean管理(FactoryBean)
-
bean的类型
- 普通bean:在配置文件中定义的bean的类型就是返回类型
- FactoryBean:在配置文件中定义的bean类型可以和返回类型不一样
-
工厂bean的实现
使类实现FactoryBean接口,实现getObject方法来返回指定的bean类型
public class MyBean implements FactoryBean <Course>{ @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } @Override public Course getObject() throws Exception { Course course = new Course(); course.setName("abcdd"); return course; } @Override public Class<Course> getObjectType() { return null; } }
-
bean的作用域
-
在spring里,可以设置创建的bean实例是单实例还是多实例,默认为单实例对象
(这里的单实例指的是所有以此法创建的对象都为同一个实例,地址相同)
-
设置实例
scope="singleton" 单实例,默认值 scope="prototype" 多实例
-
二者区别
除了单多实例的区别外,当scope值为singleton时,加载spring配置文件的时候就会创建单实例对象,设置scope为prototype时候,在调用getBean()方法时创建多实例对象
-
-
bean生命周期:
-
生命周期:从对象创建到对象销毁的过程
-
bean生命周期(斜体为后置处理器添加后的步骤):
(1) 通过构造器创建bean实例(无参构造)
(2) 为bean的属性设置值和对其他bean引用(调用set方法)
(2.1) 把bean实例传递给后置处理器的方法 执行postProcessBeforeInitialization方法
(3) 调用bean的初始化方法(需要进行配置
(3.1) 把bean实例传递给后置处理器的方法 执行postProcessAfterInitialization方法
(4) 获取到bean对象
(5) 容器关闭时,调取bean的销毁方法(具体方法需要配置)
<bean id="" class="" init-method="方法名(不用加方法名)" destroy-method="方法名"></bean>
-
-
基于xml的bean自动装配
-
概念:根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入
-
代码:
<!--实现自动装配 bean标签属性autowire,配置自动装配 autowire常用两个值: byName:根据属性名称注入,注入值bean的id和类属性名称一样 byType:根据类属性注入(自动寻找寻找特定的类)--> <bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType"> <property name="name" value="zhang"></property> <property name="gender" value="nan"></property> </bean> <bean id="dept123" class="com.atguigu.spring5.autowire.Dept"> <property name="name" value="12345"></property> </bean>
-
-
外部属性文件
(1) 创建properties文件
prop.driverClass=xxx prop.url=xx prop.userName=xxx prop.password=xxx
(2) 引入命名空间
<beansxmlns: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">></beans>
(3) 引入外部文件
<context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="---"> <property name="driverClassName" value="${prop.driverClass}"></property> <property name="url" value="${prop.url}"></property> <property name="username" value="${prop.username}"></property> <property name="password" value="${prop.password}"></property> </bean>
4 IOC操作Bean管理(基于注解方式)
-
注解:注解是代码特殊标记 格式:@name(key1= value1,…)
可以作用在类,方法,属性上面
可以简化xml配置
-
spring提供的针对bean管理中创建对象提供注解
@Component @Service @Controller @Repository //上述注解都可以用来创建对象,但是习惯使用在不同的层中
-
基于注解方式实现对象的创建
-
引入aop依赖
-
开启组件扫描
<!--扫描多个包 法一:使用逗号隔开 法二:扫描这些包的的上层目录 --> <context:component-scan base-package="com.atguigu.spring5.dao,com.atguigu.spring5.service"></context:component-scan>
-
创建类
//在注解中的value属性值可以省略,默认值为类名称,首字母小写 //通常在什么层中就 @Service(value = "userService") // <bean id="userService" class=".."> public class UserService { public void add(){ System.out.println("service add.........."); } }
-
开启组件扫描中的细节
示例一: <context:component-scan base-package="com.atguigu.spring5" use-default- filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- use-default-filters:表示是否默认扫描所有注解,false的话则需自己配置 org.springframework.stereotype.Controller 表示扫描Controller注解 --> 示例二: <context:component-scan base-package="com.atguigu.spring5" > <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 扫描下面配置包里的所有内容 context:exclude-filter:设置那些内容不进行扫描 -->
-
基于注解方式实现属性注入
@AutoWired //根据属性类型进行自动装配 /* (1) 把service和dao对象创建,在service和dao类添加创建对象注解 (2) 在service中注入dao对象,在dao类型属性上面使用注解 */ public class UserService { @Autowired private UserDao userDao; //不需要set方法 //直接添加此注解即可 public void add(){ System.out.println("service add.........."); } } @Qualifier //根据属性名称进行注入,与上述的AutoWired一同使用 public class UserService { @Autowired @Qualifier(value = "userDaoImpl1") private UserDao userDao; public void add(){ System.out.println("service add.........."); userDao.add(); } } @Resource //可以根据类型注入,也可以根据名城注入,要注意Resource在javax扩展包中的注解,不建议使用 @Resource(name = "userDaoImpl1") private UserDao userDao; @Value //注入普通类型属性 @Value(value = "abc") private String name;
-
-
完全注解开发(真实开发使用springboot)
-
创建配置类,替代xml文件
@Configuration//作为配置类,替代xml配置文件 @ComponentScan(basePackages = {"com.atguigu"}) public class SpringConfig { }
-
编写测试类
@Test public void testService2(){ //表示加载配置类 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = context.getBean("userService",UserService.class); userService.add(); }
-