IOC(概念和原理)
- 什么是 IOC
- IOC 底层原理
- xml 解析
- 工厂模式
- 反射
- 画图讲解 IOC 底层原理
IOC(beanfactory 接口)
- IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
- Spring 提供 IOC 容器实现两种方式:(两个接口)
-
beanfactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
-
ApplicationContext:beanfactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
-
- ApplicationContext 接口有实现类
IOC 操作 Bean 管理
概念
基于 xml 方式
-
基于 xml 方式创建对象
<!--配置 User 对象创建--> <bean id="user" class="com.Spring5.User"></bean>@H_404_94@
- 基于 xml 方式注入属性
- DI:依赖注入,就是注入属性
- 第一种注入方式:使用 set 方法进行注入
-
/** * 演示使用 set 方法进行注入属性 */ public class Book { //创建属性 private String bname; private String bauthor; //创建属性对应的 set 方法 public void setBname(String bname) { this.bname = bname; } public void setBauthor(String bauthor) { this.bauthor = bauthor; } }@H_404_94@
-
<!--2 set 方法注入属性--> <bean id="book" class="com.nemo.Spring5.Book"> <!--使用 property 完成属性注入 name:类里面属性名称 value:向属性注入的值 --> <property name="bname" value="易筋经"></property> <property name="bauthor" value="达摩老祖"></property> </bean> @H_404_94@
-
- 第二种注入方式:使用有参数构造进行注入
-
/** + 使用有参数构造注入 */ public class Orders { //属性 private String oname; private String address; //有参数构造 public Orders(String oname,String address) { this.oname = oname; this.address = address; } }@H_404_94@
-
在 spring 配置文件中进行配置
<!--3 有参数构造注入属性--> <bean id="orders" class="com.nemo.Spring5.Orders"> <constructor-arg name="oname" value="电脑"></constructor-arg> <constructor-arg name="address" value="China"></constructor-arg> </bean>@H_404_94@
-
- p 名称空间注入(了解)
使用 p 名称空间注入,可以简化基于 xml 配置方式-
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/schema.xsd"> </beans>@H_404_94@
-
<!--2 set 方法注入属性--> <bean id="book" class="com.nemo.Spring5.Book" p:bname="九阳神功" p:bauthor="无名氏"></bean>@H_404_94@
-
xml 注入其他类型属性
- 字面量
- 注入属性-外部 bean
public class UserService { //创建 UserDao 类型属性,生成 set 方法 private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add() { System.out.println("service add..............."); userDao.update(); } }@H_404_94@
<!--1 service 和 dao 对象创建--> <bean id="userService" class="com.nemo.Spring5.service.UserService"> <!--注入 userDao 对象 name 属性:类里面属性名称 ref 属性:创建 userDao 对象 bean 标签 id 值 --> <property name="userDao" ref="userDaoImpl"></property> </bean> <bean id="userDaoImpl" class="com.nemo.Spring5.dao.UserDaoImpl"></bean>@H_404_94@
- 注入属性-内部 bean
- 一对多关系:部门和员工
一个部门有多个员工,一个员工属于一个部门
部门是一,员工是多 -
在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
//部门类 public class Dept { private String dname; public void setDname(String dname) { this.dname = dname; } } //员工类 public class Emp { private String ename; private String gender; //员工属于某一个部门,使用对象形式表示 private Dept dept; public void setDept(Dept dept) { this.dept = dept; } public void setEname(String ename) { this.ename = ename; } public void setGender(String gender) { this.gender = gender; } }@H_404_94@
-
在 spring 配置文件中进行配置
<!--内部 bean--> <bean id="emp" class="com.nemo.Spring5.bean.Emp"> <!--设置两个普通属性--> <property name="ename" value="lucy"></property> <property name="gender" value="女"></property> <!--设置对象类型属性--> <property name="dept"> <bean id="dept" class="com.nemo.Spring5.bean.Dept"> <property name="dname" value="安保部"></property> </bean> </property> </bean>@H_404_94@
- 一对多关系:部门和员工
- 注入属性-级联赋值
-
第一种写法
<!--级联赋值--> <bean id="emp" class="com.nemo.Spring5.bean.Emp"> <!--设置两个普通属性--> <property name="ename" value="lucy"></property> <property name="gender" value="女"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> </bean> <bean id="dept" class="com.nemo.Spring5.bean.Dept"> <property name="dname" value="财务部"></property> </bean>@H_404_94@
-
第二种写法:需要用到 get 方法
<!--级联赋值--> <bean id="emp" class="com.nemo.Spring5.bean.Emp"> <!--设置两个普通属性--> <property name="ename" value="lucy"></property> <property name="gender" value="女"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> <property name="dept.dname" value="技术部"></property> </bean> <bean id="dept" class="com.nemo.Spring5.bean.Dept"> <property name="dname" value="财务部"></property> </bean>@H_404_94@
-
xml 注入集合属性
- 注入数组类型属性
- 注入 List 集合类型属性
- 注入 Map 集合类型属性
-
创建类,定义数组、list、map、set 类型属性,生成对应 set 方法
public class Stu { //1 数组类型属性 private String[] courses; //2 list 集合类型属性 private List<String> list; //3 map 集合类型属性 private Map<String,String> maps; //4 set 集合类型属性 private Set<String> sets; public void setSets(Set<String> sets) { this.sets = sets; } public void setCourses(String[] courses) { this.courses = courses; } public void setList(List<String> list) { this.list = list; } public void setMaps(Map<String,String> maps) { this.maps = maps; } }@H_404_94@
-
在 spring 配置文件进行配置
<!--1 集合类型属性注入--> <bean id="stu" class="com.nemo.Spring5.collectiontype.Stu"> <!--数组类型属性注入--> <property name="courses"> <array> <value>java 课程</value> <value>数据库课程</value> </array> </property> <!--list 类型属性注入--> <property name="list"> <list> <value>张三</value> <value>小三</value> </list> </property> <!--map 类型属性注入--> <property name="maps"> <map> <entry key="JAVA" value="java"></entry> <entry key="PHP" value="PHP"></entry> </map> </property> <!--set 类型属性注入--> <property name="sets"> <set> <value>MysqL</value> <value>Redis</value> </set> </property> </bean>@H_404_94@
-
-
在集合里面设置对象类型值
5、把集合注入部分提取出来<!--创建多个 course 对象--> <bean id="course1" class="com.nemo.Spring5.collectiontype.Course"> <property name="cname" value="Spring5 框架"></property> </bean> <bean id="course2" class="com.nemo.Spring5.collectiontype.Course"> <property name="cname" value="MyBatis 框架"></property> </bean> <!--注入 list 集合类型,值是对象--> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property>@H_404_94@
-
<?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:p="http://www.springframework.org/schema/p" xmlns: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>@H_404_94@
-
<!--1 提取 list 集合类型属性注入--> <util:list id="bookList"> <value>易筋经</value> <value>九阴真经</value> <value>九阳神功</value> </util:list> <!--2 提取 list 集合类型属性注入使用--> <bean id="book" class="com.nemo.Spring5.collectiontype.Book"> <property name="list" ref="bookList"></property> </bean>@H_404_94@
-
factorybean
- Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(factorybean)
- 普通 bean:在配置文件中定义 bean 类型就是返回类型
- 工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
- 第一步 创建类,让这个类作为工厂 bean,实现接口 factorybean
- 第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
public class MyBean implements factorybean<Course> { //定义返回 bean @Override public Course getobject() throws Exception { Course course = new Course(); course.setCname("abc"); return course; } @Override public Class<?> getobjectType() { return null; } @Override public boolean isSingleton() { return false; } }@H_404_94@
<bean id="myBean" class="com.nemo.Spring5.factorybean.MyBean"></bean>@H_404_94@
@Test public void test3() { ApplicationContext context = new ClasspathXmlApplicationContext("bean3.xml"); Course course = context.getBean("myBean",Course.class); System.out.println(course); }@H_404_94@
bean 作用域
- 在 Spring 里面,设置创建 bean 实例是单实例还是多实例
- 在 Spring 里面,默认情况下,bean 是单实例对象
- 如何设置单实例还是多实例
bean 生命周期
- 生命周期
- bean 生命周期
-
演示 bean 生命周期
public class Orders { //无参数构造 public Orders() { System.out.println("第一步 执行无参数构造创建 bean 实例"); } private String oname; public void setoname(String oname) { this.oname = oname; System.out.println("第二步 调用 set 方法设置属性值"); } //创建执行的初始化的方法 public void initMethod() { System.out.println("第三步 执行初始化的方法"); } //创建执行的销毁的方法 public void destroyMethod() { System.out.println("第五步 执行销毁的方法"); } }@H_404_94@
<bean id="orders" class="com.nemo.Spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"> <property name="oname" value="手机"></property> </bean>@H_404_94@
@Test public void testBean3() { // ApplicationContext context = // new ClasspathXmlApplicationContext("bean4.xml"); ClasspathXmlApplicationContext context = new ClasspathXmlApplicationContext("bean4.xml"); Orders orders = context.getBean("orders",Orders.class); System.out.println("第四步 获取创建 bean 实例对象"); System.out.println(orders); //手动让 bean 实例销毁 context.close(); }@H_404_94@
- bean 的后置处理器,bean 生命周期有七步
- 演示添加后置处理器效果
-
创建类,实现接口 BeanPostProcessor,创建后置处理器
public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException { System.out.println("在初始化之前执行的方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException { System.out.println("在初始化之后执行的方法"); return bean; } }@H_404_94@
<!--配置后置处理器--> <bean id="myBeanPost" class="com.nemo.Spring5.bean.MyBeanPost"> </bean>@H_404_94@
-
xml 自动装配
- 什么是自动装配
- 演示自动装配过程
-
<!--实现自动装配 bean 标签属性 autowire,配置自动装配 autowire 属性常用两个值: byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样 byType 根据属性类型注入 --> <bean id="emp" class="com.nemo.Spring5.autowire.Emp" autowire="byName"> <!--<property name="dept" ref="dept"></property>--> </bean> <bean id="dept" class="com.nemo.Spring5.autowire.Dept"></bean>@H_404_94@
-
<!--实现自动装配 bean 标签属性 autowire,配置自动装配 autowire 属性常用两个值: byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样 byType 根据属性类型注入 --> <bean id="emp" class="com.nemo.Spring5.autowire.Emp" autowire="byType"> <!--<property name="dept" ref="dept"></property>--> </bean> <bean id="dept" class="com.nemo.Spring5.autowire.Dept"></bean>@H_404_94@
-
外部属性文件
连接池:
连接池的作用就是管理连接,因为如果单纯的用JDBC去连接的话,频繁的开启 和关闭连接对于数据库也是一种负担。使用连接池技术后,可以不必频繁开启关闭连接 需要的时候就去用就好了,这样是资源重用,而且有更快的系统反应速度
市面上实现作为连接池的方案有很多 c3p0 阿里的 druid(德鲁伊) 等 都是很不错的 实现方式
- 直接配置数据库信息
- 配置德鲁伊连接池
- 引入德鲁伊连接池依赖 jar 包
<!--直接配置连接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.MysqL.jdbc.Driver"></property> <property name="url" value="jdbc:MysqL://localhost:3306/userDb"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>@H_404_94@
- 引入外部属性文件配置数据库连接池
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" 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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> @H_404_94@
<!--引入外部属性文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--配置连接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <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>@H_404_94@
基于注解方式
- 什么是注解
- Spring 针对 Bean 管理中创建对象提供注解
1、@Service用于标注业务层组件
2、@Controller用于标注控制层组件(如struts中的action)
3、@Repository用于标注数据访问组件,即DAO组件.
4、@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 - 基于注解方式实现对象创建
- 第一步 引入依赖
-
第二步 开启组件扫描
<!--开启组件扫描 1 如果扫描多个包,多个包使用逗号隔开 2 扫描包上层目录 --> <context:component-scan base-package="com.nemo"></context:component-scan>@H_404_94@
-
第三步 创建类,在类上面添加创建对象注解
//在注解里面 value 属性值可以省略不写, //默认值是类名称,首字母小写 //UserService -- userService @Component(value = "userService") //<bean id="userService" class=".."/> public class UserService { public void add() { System.out.println("service add......."); } }@H_404_94@
-
开启组件扫描细节配置
<!--示例 1 use-default-filters="false" 表示现在不使用默认 filter,自己配置 filter context:include-filter ,设置扫描哪些内容 --> <context:component-scan base-package="com.nemo" use-defaultfilters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!--示例 2 下面配置扫描包所有内容 context:exclude-filter: 设置哪些内容不进行扫描 --> <context:component-scan base-package="com.nemo"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>@H_404_94@
- 基于注解方式实现属性注入
- @Autowired:根据属性类型进行自动装配
- 第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解
- 第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
@Service public class UserService { //定义 dao 类型属性 //不需要添加 set 方法 //添加注入属性注解 @Autowired private UserDao userDao; public void add() { System.out.println("service add......."); userDao.add(); } }@H_404_94@
-
@Qualifier:根据名称进行注入
这个@Qualifier 注解的使用,和上面@Autowired 一起使用//定义 dao 类型属性 //不需要添加 set 方法 //添加注入属性注解 @Autowired //根据类型进行注入 @Qualifier(value = "userDaoImpl1") //根据名称进行注入 private UserDao userDao;@H_404_94@
-
@Resource:可以根据类型注入,可以根据名称注入
//@Resource //根据类型进行注入 @Resource(name = "userDaoImpl1") //根据名称进行注入 private UserDao userDao;@H_404_94@
-
@Value:注入普通类型属性
注意:开发中会用到@value去动态读取服务器端口号,或者是配置环境是生产环境还是上线环境等等。。
@Value(value = "abc") private String name; @H_404_94@
- @Autowired:根据属性类型进行自动装配
- 完全注解开发
-
创建配置类,替代 xml 配置文件
@Configuration //作为配置类,替代 xml 配置文件 @ComponentScan(basePackages = {"com.nemo"}) public class SpringConfig { }@H_404_94@
-
编写测试类
@Test public void testService2() { //加载配置类 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = context.getBean("userService",UserService.class); System.out.println(userService); userService.add(); }@H_404_94@
-
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。