目录
BeanFactory与ApplicationContext的关系
Spring Framework 的整体架构
spring分为四部分
➀第一部分ioc基础容器
➁第二部分面向切面编程
➂第三部分spring整合web环境
➃第四部分web层解决方案springmvc
传统javaweb开发问题
1.层与层,接口与具体实现紧密耦合
解决:第三方为程序提供需要的bean对象
2.通用的事务功能和日志功能耦合在业务代码中
解决:第三方根据要求为程序提供需要的bean对象的代理对象
IOC DI AOP概念
○IOC (Inversion Of Control)控制反转,将原来在程序中创建bean的权利转让给第三方
由主动new对象转为IOC容器创建和初始化,IOC容器管理的对象叫做bean
○DI(Dependency Injection)依赖注入,强调bean之间的关系,由第三方配置.在IOC容器中将有依赖关系的bean进行关系绑定
○AOP(Aspect Oriented Programming)面向切面编程,功能的横向抽取,,主要的实现方式是Proxy,对某一个bean进行增强
框架
❶基于基础技术上,从众多业务中抽取出来的通用解决方案
❷框架是一个半成品,使用框架可以提高开发效率,使用简单的代码完成复杂的业务
❸框架内部使用大量的设计模式,算法,底层代码操作技术,如反射,xml解析等
❹框架一般都具有扩展性
❺框架使程序员集中在业务开发中
※ java常用框架
★基础框架:Mybits,Spring,SpringMVC,Struts2,Hibernate等
★服务框架:MQ,ES,Nacos等
Spring框架
Spring官网 www.spring.io
BeanFactory快速入门
程序代码 ---> 第三方 --->配置清单 --->bean类
1)导入Spring的jar包或者Maven坐标
2)定义UserService接口及其UserServiceImpl实现类
3)创建beans.xml配置文件,将UserServiceImpl的信息配置到该xml中
4)编写测试代码,创建BeanFactory,加载配置文件,获取UserService实例对象
1)创建maven项目,在pom.xml中添加依赖
<dependencies>
<!-- 1.Spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
</dependencies>
2)
public interface UserService {
}
public class UserServiceImpl implements UserService {
}
3)创建beans.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">
<!-- 配置UserServiceImpl -->
<bean id="userService" class="com.ting.service.impl.UserServiceImpl"></bean>
</beans>
4)编写测试代码
public class BeanFactoryTest {
public static void main(String[] args) {
//1.创建工厂对象 beanFactory
DefaultListableBeanFactory beanFactory =new DefaultListableBeanFactory();
//2.创建一个读取器(xml文件)
XmlBeanDefinitionReader reader =new XmlBeanDefinitionReader(beanFactory);
//3.读取配置文件给工厂
reader.loadBeanDefinitions("beans.xml");
//4.根据ID获取bean实例对象
UserService userService = (UserService) beanFactory.getBean("userService");
System.out.println(userService);
}
}
DI依赖注入
1)定义UserDao接口及UserDaoImpl实现类
2)修改UserServiceImpl代码,添加一个setUserDao(UserDao userDao)用于接收注入的对象
3)修改beans.xml配置文件,在UserServiceImpl的<bean>中嵌入<property>配置注入
4)修改测试代码,在获得UserService时,setUserDao执行了注入操作
1)创建UserDao,UserDaoImpl
public interface UserDao {
}
public class UserDaoImpl implements UserDao {
}
2)
public class UserServiceImpl implements UserService {
private UserDao userDao;
//BeanFactory调用该方法 从容器中获取userDao设置到此处
public void setUserDao(UserDao userDao){
System.out.println("BeanFactory调用该方法"+userDao);
this.userDao = userDao;
}
}
3)配置xml
<bean id="userService" class="com.ting.service.impl.UserServiceImpl">
<!--注意: 这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写-->
<!--引用另外一个bean , 不是用value 而是用 ref-->
<property name="userDao" ref="userDao"></property>
</bean>
<!--配置UserDaoImpl-->
<bean id="userDao" class="com.ting.dao.impl.UserDaoImpl"/>
4)测试代码
public class BeanFactoryTest {
public static void main(String[] args) {
//1.创建工厂对象
DefaultListableBeanFactory beanFactory =new DefaultListableBeanFactory();
//2.创建一个读取器(xml文件)
XmlBeanDefinitionReader reader =new XmlBeanDefinitionReader(beanFactory);
//3.读取配置文件给工厂
reader.loadBeanDefinitions("beans.xml");
//4.根据ID获取bean实例对象
UserService userService = (UserService) beanFactory.getBean("userService");
//System.out.println(userService);
//UserDao userDao = (UserDao) beanFactory.getBean("userDao");
// System.out.println(userDao);
//service调用dao,设置set方法
}
}
ApplicationContext快速入门
ApplicationContext称为spring容器,内部封装了BeanFactory,比BeanFactory功能丰富强大,使用ApplicationContext进行开发时,xml配置文件的名称一般为applicationContext.xml
//创建applicationContext 加载配置文件 实例化容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//根据beanName 获取容器中bean实例
UserService userService =(UserService) applicationContext.getBean("userService");
System.out.println("userService");
BeanFactory与ApplicationContext的关系
1)BeanFactory是spring早期接口,称为spring的Bean工厂,ApplicationContext是后期更高级接口,称为spring容器
2)ApplicationContext在BeanFactory基础上对功能进行扩展,例如监听功能,国际化功能等。BeanFactory的API更偏向底层,ApplicationContext的API大多数都是对底层API的封装
3)Bean创建的主要功能和逻辑都封装在BeanFactory中,ApplicationContext不仅继承了BeanFactory,而且ApplicationContext内部维护着BeanFactory的引用。
4)Bean的初始化时机不同,原始BeanFactory是在首次调用getBean时才创建Bean,而ApplicationContext是配置文件加载,在容器创建时对Bean进行实例化并且初始化好
ApplicationContext的继承体系
只在Spring基础环境下,常用的三个ApplicationContext作用如下
1.ClassPathXmlApplicationContext
加载类路径下的xml配置的ApplicationContext
2.FileSystemXmlApplicationContext
加载磁盘路径下的xml配置的ApplicationContext
3.AnnotationConfigApplicationContext
加载注解配置类的ApplicationContext
IOC 入门案例(Xml)
1.管理什么(Service和Dao)
2.如何将被管理的对象告知IOC容器(配置)
3.被管理的对象交给IOC容器,如何获取到IOC容器(接口)
4.IOC容器得到后,如何从容器中获取bean(接口方法)
5.使用spring导入哪些坐标(pom.xml)
♡ 项目结构
1)导入spring-context
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
</dependencies>
2)定义spring管理的类和接口
public interface BookService {
void save();
}
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save(){
System.out.println("book service save ...");
bookDao.save();
}
}
3)创建配置文件applicationContext.xml,配置对应类作为spring管理的bean
<bean id="bookService" class="com.ting.service.impl.BookServiceImpl"></bean>
注:bean配置时,id属性在同一个上下文不能重复
4)初始化IOC容器(spring核心容器、spring容器),通过容器获取bean
public class App2 {
public static void main(String[] args) {
//3.获取IOC容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//4.获取bean
BookService bookService= (BookService) applicationContext.getBean("bookService");
bookService.save();
}
}
DI入门案例
1)基于IOC管理bean
2)Service中使用new创建的Dao对象是否保留(否)
3)Service中需要的Dao对象如何进入Service中(提供方法)
4)Service与Dao的关系如何描述(配置)
public class BookServiceImpl implements BookService {
//5 删除业务层中使用new的方式创建的dao对象
private BookDao bookDao ;
// 6 生成一个set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save(){
System.out.println("book service save ...");
bookDao.save();
}
}
<bean id="bookDao" class="com.ting.dao.impl.BookDaoImpl"></bean>
<!--7 配置dao和service的关系-->
<bean id="bookService" class="com.ting.service.impl.BookServiceImpl">
<!--property标签表示配置当前bean的属性-->
<!--name属性表示配置哪一个具体的属性-->
<!--ref属性表示参照哪一个bean-->
<property name="bookDao" ref="bookDao"></property>
</bean>
bean的xml配置
功能:定义spring核心容器管理的对象
格式:<beans>
<bean></bean>
</beans>
属性列表:id ,使用容器可以通过id值获取到对应的bean,在一个容器中bean唯一
class ,bean的类型,即配置bean的全路径名
bean别名配置:name定义bean的别名,可以定义多个,用逗号,分号,空格分隔
<bean id="bookDao" name="dao dao2 bookDao2" class="com.ting.dao.impl.BookDaoImpl"></bean>
bean作用范围:scope,控制bean创建的实例数量
在Spring中,bean的作用范围分以下几种:
singleton:spring ioc容器中仅有一个bean实例,bean以单例的方式存在(默认)
prototype:每次从容器中调用bean时,都返回一个新的实例
request:每次http请求都会创建一个新的bean
session:同一个http session共享一个bean
global session:同一个全局session共享一个bean 一般用于portlet应用环境
application:同一个application共享一个bean
<bean id="bookDao" class="com.ting.dao.impl.BookDaoImpl" scope="singleton"></bean>
适合交给容器管理的bean
○表现层对象 ○业务层对象 ○数据层对象 ○工具对象
不适合交给容器管理的bean
○封装实体的域对象
bean的常用配置
○ <bean id=" " class=" " /> bean的id和全限定名配置
id是配置文件唯一标识
如果不配置id,当前bean仍有bean name ,为当前bean的全限定名
○<bean name=" " /> 通过name设置bean的别名,通过别名也能获取到bean实例
○<bean scope =" " />bean的作用范围,BeanFactory 作为容器时取值singleton和prototype
○<bean lazy-init =" " />bean实例化时是否延迟加载,BeanFactory 作为容器时无效
○<bean init-method =" " /> bean实例化后自动执行的初始化方法 ,method指定方法名
○<bean destroy-method =" " /> bean实例化后的销毁前方法 ,method指定方法名
除此之外,我们还可以通过实现InitializingBean接口,完成一些Bean的初始化操作,如下:
public class UserDaoImpl implements UserDao,InitializingBean {
public UserDaoImpl()
{System.out.println("UserDaoImpl创建了...");}
public void init()
{System.out.println("初始化方法...");}
public void destroy()
{System.out.println("销毁方法...");
}
//执行时机早于init-method配置的方法
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean...");
}
}
初始化两种方法
1.init方法
2.实现接口InitializingBean复写afterPropertiesSet
○<bean autowird ="byType " /> 设置自动注入模式,常用的有按照类型byType,按照名字byName
○<bean factory-method=" " factory-bean=""/> 指定哪个工厂的bean的那个方法完成bean的创建
bean 实例化
1.使用无参构造(常用)
BookDao,BookDaoImpl,xml配置文件
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println("book dao save ...");
}
}
<bean id="bookDao" class="com.ting.dao.impl.BookDaoImpl"></bean>
运行程序
public class App3 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
bookDao.save();
}
}
public class BookDaoImpl implements BookDao {
public BookDaoImpl(){
System.out.println("book dao constructor is running......");
}
public void save(){
System.out.println("book dao save ...");
}
}
2.有参构造方法
public UserDaoImpl(String name){
}
有参构造在实例化Bean时,需要参数的注入,通过<constructor-arg>标签,嵌入在<bean>标签内部提供构造参数,如下:
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<constructor-arg name="name"value="haohao"/>
</bean>
3.使用静态工厂方法实例化(简单工厂模式)(了解)
public interface OrderDao {
public void save();
}
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("order dao save ..." );
}
}
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory start up");
return new OrderDaoImpl();
}
}
public class App4 {
public static void main(String[] args) {
OrderDao orderDao= OrderDaoFactory.getOrderDao();
orderDao.save();
}
}
<!--静态工厂实现bean-->
<bean id="orderDao" class="com.ting.factory.OrderDaoFactory" factory-method="getOrderDao"/>
4.实例工厂实例化bean
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("user dao save...");
}
}
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
public class App5 {
public static void main(String[] args) {
//创建实例工厂对象
UserDaoFactory userDaoFactory = new UserDaoFactory();
//通过实例工厂对象创建对象
UserDao userDao =userDaoFactory.getUserDao();
userDao.save();
}
}
<!--实例工厂实例化bean-->
<!--造工厂对象-->
<bean id="userFactory" class="com.ting.factory.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"></bean>
改进
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//代替原始实例工厂中创建对象的方法
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
@Override
public Class<?> getObjectType() {
return UserDao.class;
}
//加上此方法为单例
@Override
public boolean isSingleton() {
return true;//return false; 非单例
}
}
<!--FactoryBean实例化-->
<bean id="userDao" class="com.ting.factory.UserDaoFactoryBean"/>
bean的生命周期
生命周期:从创建到销毁的完整过程
bean生命周期:bean从创建到销毁的完整过程
bean生命周期控制:在bean从创建后到销毁前做一些事情
Bean的依赖注入配置
Bean的依赖注入有两种方式:
1.通过Bean的set方法注入
<property name="userDao" ref="userDao"/>
<property name="userDao" value="haohao"/>
2.通过构造Bean的方法进行注入
<constructor-arg name="name" ref="userDao" />
<constructor-arg name="name" value="haohao"/>
Spring的其他配置标签
Spring的xml标签大体上分为两类,一种是默认标签,一种是自定义标签
默认标签:就是不用额外导入其他命名空间约束的标签,例如<bean>标签
自定义标签:就是需要额外引入其他命名空间约束,并通过前缀引用的标签,例如<context:property-placeholder/> 标签
Spring的默认标签用到的是Spring的默认命名空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmins="http://www.springframework.org/schema/beans"
xmins: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">
</beans>
该命名空间约束下的默认标签如下:
<beans> 一般作为xml配置根标签,其他标签都是该标签的子标签
<bean> Bean的配置标签
<import> 外部资源导入标签
<aliast 指定Bean的别名标签,使用较少
<beans>标签,除了经常用的做为根标签外,还可以嵌套在根标签内,使用profile属性切换开发环境
<!--配置测试环境下,需要加载的Bean实例 -->
<beans profile="test">
</beans>
<!-- 配置开发环境下,需要加载的Bean实例 -->
<beans profile="dev">
<beans>
可以使用以下两种方式指定被激活的环境:
使用命令行动态参数,虚拟机参数位置加载-Dspring.profiles.active=test
使用代码的方式设置环境变量System.setProperty("spring.profiles.active","test")
<import>标签,用于导入其他配置文件,项目变大后,就会导致一个配置文件内容过多,可以将一个配置文件根据业务某块进行拆分,拆分后,最终通过<import>标签导入到一个主配置文件中,项目加载主配置文件就连同<import>导入的文件一并加载了
<!--导入用户模块配置文件-->
<import resource="classpath:UserModuleApplicationContext.xml"/>
<!--导入商品模块配置文件-->
<import resource="classpath:ProductModuleApplicationContext.xml"/>
<alias> 标签是为某个Bean添加别名,与在<bean> 标签上使用name属性添加别名的方式一样,我们为
UserServicelmpl指定四个别名:aaa、bbb、xxx、yyy
<!-配置UserService-->
<bean id="userService" name="aaa,bbb"class="com.itheima.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<!--指定别名-->
<alias name="userService"alias="xxx"/>
<alias name="userServida"alias="yyy"/>
Spring的自定义标签需要引入外部的命名空间,并为外部的命名空间指定前缀,使用<前缀:标签>形式的标签,称之为自定义标签
1.导入spring-web-mvc依赖
2
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-默认标签-->
<bean id="userDao"class="com.ting.dao.impl.UserDaoImpl"/>
<!--自定义标签-->
<context:property-placeholder/>
<mvc:annotation-driven/>
<dubbo:application name="application"/>
<?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">
<context:property-placeholder></context:property-placeholder>
Spring常用的三种getBean的API
基于xml的Spring应用
Spring 的get方法
Object getBean (String beanName)
根据beanName从容器中获取Bean实例,要求容器中Bean唯一,返回值为Object,需要强转
T getBean (Class type)
根据Class类型从容器中获取Bean实例,要求容器中Bean类型唯一,返回值为Class类型实例
无需强转
T getBean (String beanName,Class type)
根据beanName从容器中获得Bean实例,返回值为Class类型实例,无需强转
//根据beanName获取容器中的Bean实例,需要手动强转
UserService userService= (UserService)applicationContext.getBean("userService");
//根据Bean类型去容器中匹配对应的Bean实例,如存在多个匹配Bean则报错
UserService userService2= applicationContext.getBean(UserService.class);
//根据beanName获取容器中的Bean实例,指定Bean的Type类型
UserService userService3= applicationContext.getBean("userService"
UserService.class);