Spring入门
引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
结构:
创建UserService及UserServiceImpl
public interface UserService {}
import com.hngc.spring.dao.UserDao;
import com.hngc.spring.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
/**
* BeanFactory自动调用该方法,将容器内userDao设置到此处
*
* @param userDao userDao
*/
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
创建UserDao及UserDaoImpl
public interface UserDao {}
import com.hngc.spring.dao.UserDao;
public class UserDaoImpl implements UserDao {
}
Spring配置文件
<?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">
<!-- 配置userService-->
<bean id="userService" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 配置userMapper-->
<bean id="userDao" class="com.hngc.spring.dao.impl.UserDaoImpl"></bean>
</beans>
BeanFactory方式
测试类
import com.hngc.spring.service.UserService;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
public class SpringDemo {
public static void main(String[] args) {
//创建BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//创建读取器
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
//加载配置文件
reader.loadBeanDefinitions("beans.xml");
//获取Bean实例对象
UserService bean = (UserService) beanFactory.getBean("userService");
System.out.println(bean);
}
}
运行结果:
com.hngc.spring.service.impl.UserServiceImpl@3590fc5b
ApplicationContext方式(推荐)
ApplicationContext是BeanFactory的子类,并融合了其他扩展,功能也更加强大
配置文件
放在 resources 目录下,配置文件名称自定义,一般规范命名为applicationContext.xml,内容和之前BeanFactory一样
<?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">
<!-- 配置userService-->
<bean id="userService" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 配置userMapper-->
<bean id="userDao" class="com.hngc.spring.dao.impl.UserDaoImpl"></bean>
</beans>
测试类:
import com.hngc.spring.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextDemo {
public static void main(String[] args) {
//加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取Bean实例对象
UserService userService = (UserService) applicationContext.getBean("userService");
System.out.println(userService);
}
}
运行输出:
com.hngc.spring.service.impl.UserServiceImpl@6a370f4
构造方法实例化Bean
默认情况下会调用UserServiceImpl无参构造实例化
若想要调用有参构造实例化Bean需提供有参构造并在配置文件添加constructor-arg标签传递参数
<!-- 配置userService-->
<bean id="userService" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
<constructor-arg name="username" value="test"></constructor-arg>
</bean>
<!-- 配置userMapper-->
<bean id="userDao" class="com.hngc.spring.dao.impl.UserDaoImpl"></bean>
import com.hngc.spring.dao.UserDao;
import com.hngc.spring.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl() {
System.out.println("调用无参构造...");
}
public UserServiceImpl(String username) {
System.out.println("调用参构造...");
}
/**
* BeanFactory调用该方法,将容器内userDao设置到此处
*
* @param userDao userDao
*/
@Override
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
工厂实例化Bean
静态工厂实例化Bean
import com.hngc.spring.dao.UserDao;
import com.hngc.spring.dao.impl.UserDaoImpl;
public class MyFactoryBean {
/**
* 静态工厂 可在实例化之前z做一些业务操作
* @param username
* @return
*/
public static UserDao userDao(String username) {
return new UserDaoImpl();
}
}
配置文件
<!-- 调用静态方法实例化-->
<bean id="userDao1" class="com.hngc.spring.factory.MyFactoryBean" factory-method="userDao">
<constructor-arg name="username" value="test"></constructor-arg>
</bean>
实例工厂实例化Bean
<!--配置工厂对象-->
<bean id="myFactoryBean2" class="com.hngc.spring.factory.MyFactoryBean2"></bean>
<!--实例化Bean-->
<bean id="userDao2" factory-bean="myFactoryBean2" factory-method="userDao"></bean>
import com.hngc.spring.dao.UserDao;
import com.hngc.spring.dao.impl.UserDaoImpl;
public class MyFactoryBean2 {
public UserDao userDao() {
return new UserDaoImpl();
}
}
实现BeanFactory延迟加载实例化Bean
懒加载
import com.hngc.spring.dao.UserDao;
import com.hngc.spring.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean3 implements FactoryBean<UserDao> {
/**
*
* @return 返回的Bean
* @throws Exception
*/
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
/**
*
* @return 返回Bean的类型
*/
@Override
public Class<?> getObjectType() {
return UserDao.class;
}
}
配置文件
<bean id="userDao3" class="com.hngc.spring.factory.MyFactoryBean3"></bean>
Bean依赖注入配置
其中,ref是 reference的缩写形式,翻译为:涉及,参考的意思,用于引用其他Bean的id。value用于注入普通属性值。
注入方式 | 配置方式 |
---|---|
通过Bean的set方法注入 | <property name="userDao" ref="userDao"></property> <property name="userDao" ref="userDao"></property> |
通过构造bean1方法进行注入 | <constructor-arg name="username" value="userDao"></constructor-arg>``<constructor-arg name="username" value="userDao"></constructor-arg> |
注入List集合属性
示例
private List<String> stringList;
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
配置
属性为普通类型
<bean id="userService1" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="stringList">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
</bean>
属性为bean类型
private List<UserDao> userDaoList;
public void setUserDaoList(List<UserDao> userDaoList) {
this.userDaoList = userDaoList;
}
<bean id="userService1" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="userDaoList">
<list>
<bean id="userDao1" factory-bean="myFactoryBean2" factory-method="userDao"></bean>
<bean id="userDao2" factory-bean="myFactoryBean2" factory-method="userDao"></bean>
<bean id="userDao3" factory-bean="myFactoryBean2" factory-method="userDao"></bean>
</list>
</property>
</bean>
注入Set集合属性
示例
private Set<String> stringSet;
public void setStringSet(Set<String> stringSet) {
this.stringSet = stringSet;
}
配置
属性为普通类型
<bean id="userService1" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="stringSet">
<set>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</set>
</property>
</bean>
属性为bean类型
private Set<UserDao> userDaoSet;
public void setUserDaoSet(List<UserDao> userDaoSet) {
this.userDaoSet = userDaoSet;
}
<bean id="userService1" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="userDaoSet">
<set>
<bean id="userDao1" factory-bean="myFactoryBean2" factory-method="userDao"></bean>
<bean id="userDao2" factory-bean="myFactoryBean2" factory-method="userDao"></bean>
<bean id="userDao3" factory-bean="myFactoryBean2" factory-method="userDao"></bean>
</set>
</property>
</bean>
注入map集合属性
private Map<String,String> stringMap;
public void setStringMap(Map<String, String> stringMap) {
this.stringMap = stringMap;
}
<bean id="userService3" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="stringMap">
<map>
<entry key="username" value="zhangsan"></entry>
<entry key="age" value="18"></entry>
</map>
</property>
</bean>
自动装配
自动装配可选byName和byType(不推荐,因为当有多个类型相同的Bean时会出现错误)
<!-- 配置userService-->
<bean id="userService" class="com.hngc.spring.service.impl.UserServiceImpl" autowire="byName"></bean>
<!-- 配置userMapper-->
<bean id="userDao" class="com.hngc.spring.dao.impl.UserDaoImpl"></bean>
基于xml的Spring应用
Bean 实例化的基本流程
- 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象;
- 将BeanDefinition存储在一个名为beanDefinitionMap的Map<String,BeanDefinition>中;
- ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象;
- 创建好的Bean实例对象,被存储到一个名为singletonObjects的Map<String,Object>中;
- 当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回。
spring后处理器
Bean生命周期
xml方式整合第三方框架
整合mybatis
Spring整合MyBatis的原理剖析
整合包里提供了一个SqlSessionFactoryBean和一个扫描Mapper的配置对象,SqlSessionFactoryBean一旦被实例化,就开始扫描Mapper并通过动态代理产生Mapper的实现类存储到Sping容器中。相关的有如下四个类:
- SqlSessionFactoryBean:需要进行配置,用于提供SqlSessionFactory
- MapperScannerConfig:需要进行配置,用于扫描指定Mapper注册BeanDefinition
- MapperFactoryBean:Mapper的FactoryBean,获取指定Mapper时调用getObject方法
- ClassPathMapperScanner:definition.setAutowireMode(2)修改了自动注入状态,所以MapperFactoryBean中的setSqlSessionFactory会自动注入进去
引入依赖:
<!-- mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<!-- spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.21</version>
</dependency>
<!-- mybatis-spring-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
编写spring配置文件
<bean id="userService" class="com.hngc.spring.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
</bean>
<!-- 配置数据源信息-->
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"></property>
<property name="username" value="Java"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 配置sqlSessionFactoryBean,作用:将sqlSessionFactoryBean初始化到容器-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"></property>
</bean>
<!-- 配置mapperScannerConfigurer,作用:扫描指定的包,产生mapper对象存储到spring容器-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.hngc.spring.mapper"></property>
</bean>
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"></property>
</bean>
<!-- 配置mapperScannerConfigurer,作用:扫描指定的包,产生mapper对象存储到spring容器-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.hngc.spring.mapper"></property>
</bean>