Spring 配置文件

Bean 标签配置

<bean id="userDao" class="com.vsneko.dao.impl.UserDaoImpl" scope="singleton"></bean>
  • singleton:默认值,单例的。
    • 对象创建:当应用加载,创建容器时,对象被创建。
    • 对象运行:只要容器在,对象一直活着。
    • 对象销毁:当应用卸载,销毁容器时,对象被销毁。
  • prototype:多例的。
    • 对象创建:使用对象时,创建新的对象实例。
    • 对象运行:只要对象在使用中,就一直活着。
    • 对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收。
  • request:WEB 项目中,Spring 创建一个 Bean 对象,将对象存入到 request 域中。
  • session:WEB 项目中,Spring 创建一个 Bean 对象,将对象存入到 session 域中。
  • global session:WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境,那么 globalSession 相当于 session。

Bean 标签范围配置

<bean id="userDao" class="com.vsneko.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
  • init-method:指定类中的初始化方法名称。
  • destroy-method:指定类中销毁方法名称。

Bean 实例化的三种方式

无参构造方法实例化

<bean id="userDao" class="com.vsneko.dao.impl.UserDaoImpl"></bean>

工厂静态方法实例化

<bean id="userDao" class="com.vsneko.factory.StaticFactory" factory-method="getUserDao"></bean>

工厂实例方法实例化

<bean id="factory" class="com.vsneko.factory.DynamicFactory"></bean>
<bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>

Bean 依赖注入方式

Set 方法注入

public UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
<bean id="userDao" class="com.vsneko.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.vsneko.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<?xml version="1.0" encoding="UTF-8"?>
<!--引入 P 命名空间-->
<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">

<bean id="userDao" class="com.vsneko.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.vsneko.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>

</beans>

使用构造方法注入

public UserDao userDao;
public UserServiceImpl() {}
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
<bean id="userDao" class="com.vsneko.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.vsneko.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>

Bean 依赖注入的数据类型

普通数据类型

private String name;
private String addr;
<bean id="u1" class="com.vsneko.domain.User">
<property name="name" value="Zhangsan"></property>
<property name="addr" value="Beijing"></property>
</bean>

引用数据类型

private List<String> strList;
private Map<String, User> userMap;
private Properties properties;
<bean id="userDao" class="com.vsneko.dao.impl.UserDaoImpl">
<property name="strList">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>

<property name="userMap">
<map>
<entry key="user1" value-ref="u1"></entry>
<entry key="user2" value-ref="u2"></entry>
</map>
</property>

<property name="properties">
<props>
<prop key="p1">ppp1</prop>
<prop key="p2">ppp2</prop>
</props>
</property>
</bean>

引入其他配置文件(分模块开发)

<import resource="applicationContext-user.xml" />

ApplicationContext 的实现类

ClassPathXmlApplicationContext

它是从类的根路径下加载配置文件,推荐使用。

ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");

FileSystemXmlApplicationContext

它是从磁盘路径下加载配置文件,配置文件可以在磁盘的任意位置。

ApplicationContext app = new FileSystemXmlApplicationContext("path");

AnnotationConfigApplicationContext

当使用注解配置容器对象时,需要使用此类来创建 spring 容器,它用来读取注解。

Spring 配置数据源

数据源(连接池)的作用

  • 数据源(连接池)是提高程序性能的。
  • 事先实例化数据源,初始化部分连接资源。
  • 使用连接资源时从数据源中获取。
  • 使用完毕后将连接资源归还给数据源。

数据源的手动创建

  1. pom.xml 文件中导入 c3p0druid 的坐标。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
  1. 在方法中配置数据源
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser("root");
dataSource.setPassword("root");

Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("root");

DruidPooledConnection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
  1. 提取配置文本到配置文件 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
// 读取配置文件
ResourceBundle rb = ResourceBundle.getBundle("jdbc");
rb.getString("jdbc.driver");
rb.getString("jdbc.url");
rb.getString("jdbc.username");
rb.getString("jdbc.password");

Spring 配置数据源

可以将 DataSource 的创建权交由 Spring 容器去完成。

  1. 在 pom.xml 文件中导入 spring-context 的坐标。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
  1. applicationContext.xml 中配置注入
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
  1. 使用
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource) app.getBean(DataSource.class);

Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();

XML 加载配置文件

需要引入 context 命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 加载外部 properties 文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>

</beans>

Spring 原始注解

Spring 原始注解主要是替代 <Bean> 的配置

注解列表

注解 说明
@Component 使用在类上,用于实例化 Bean
@Controller 使用在 Web 层类上,用于实例化 Bean
@Service 使用在 Service 层类上,用于实例化 Bean
@Repository 使用在 Dao 层类上,用于实例化 Bean
@Autowired 使用在字段上,用于根据类型依赖注入
@Qualifier 结合 @Autowired 一起使用,用于根据名称进行依赖注入
@Resource 结合 @Autowired + @Qualifier 一起使用,按照名称进行注入
@Value 注入普通属性
@Scope 标注 Bean 的作用范围
@PostConstruct 使用在方法上,标注该方法是 Bean 的初始化方法
@PreDestroy 使用在方法上,标注该方法是 Bean 的销毁方法

注解的使用

  1. 在需要配置的Bean类上面加上注解 @Component("id") ( @Repository, @Service, @Controller )。
@Repository("userDao")
public class UserDaoImpl implements UserDao {

public void save() {
System.out.printf("save running");
}
}
  1. 如果要注入属性,可以用 @Autowired@Qualifier 来注入。
@Service("userService")
public class UserServiceImpl implements UserService {

@Autowired
@Qualifier("userDao")
private UserDao userDao;

public void save() {
userDao.save();
}
}
  1. 要在 applicationContext.xml 配置文件中,配置组件扫描(需要引入Context包)。
<?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:component-scan base-package="com.vsneko"></context:component-scan>
</beans>

注解使用一些细节

  • @Repository, @Service, @Controller@Component 是一样的效果,只是具有语义化,增加可读性。
  • 对于属性,如果只标记 @Autowired ,也是可以注入的,这个时候 Spring 会根据属性的类型来匹配 Spring 容器中的 Bean 进行注入。
  • 如果标记 @Autowired 的属性类型在容器中有多个 Bean,则需要用到 @Qualifier 来标识注入的 Bean 的 id,@Qualifier 必须配合 @Autowired 来使用。
  • 如果同时使用 @Autowired@Qualifier ,则可以使用 @Resource 来代替。
@Service("userService")
public class UserServiceImpl implements UserService {

@Resource(name="userDao")
private UserDao userDao;

public void save() {
userDao.save();
}
}

注入普通属性值

使用 @Value 注解可以注入普通属性值,可以使用 ${key} 来注入配置项的值。

<!-- applicationContext.xml -->
<!-- 加载外部 properties 文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
@Service("userService")
public class UserServiceImpl implements UserService {

@Value("abc")
private String text;

@Value("${jdbc.driver}")
private String driver;

}

注解标记 Bean 的作用范围

使用 @Scope 注解可以标记 Bean 的作用范围 (单例: singleton, 多例: prototype)。

@Service("userService")
@Scope("singleton")
public class UserServiceImpl implements UserService {

}

注解标记 Bean 的创建和销毁方法

使用 @PostConstruct@PreDestroy 注解可以标记 Bean 的创建和销毁方法。

@Service("userService")
public class UserServiceImpl implements UserService {

@PostConstruct
public void init(){
System.out.printf("init");
}
@PreDestroy
public void destroy(){
System.out.printf("destroy");
}
}

Spring 新注解

以下配置无法使用原始注解来代替,这时需要使用新注解。有了新注解,可以完全替代配置文件。

  • 非自定义的 Bean 配置
  • 加载 properties 文件的配置
  • 组件扫描的配置
  • 引入其他文件的配置

新注解列表

注解 说明
@Configuration 用于指定当前类是一个 Spring 配置类,创建容器时会从该类上加载注解
@ComponentScan 用于指定 Spring 初始化容器时要扫描的包。
@Bean 用在方法上,标注将该方法的返回值存储在 Spring 容器中。
@PropertySource 用于加载 properties 文件中的配置
@Import 用于导入其他配置类

新注解的使用

// 标志该类是 Spring 的核心配置类
@Configuration
// <context:component-scan base-package="com.vsneko"></context:component-scan>
@ComponentScan("com.vsneko")
// 导入其他配置类
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {

}
//<context:property-placeholder location="classpath:jdbc.properties"/>
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {

@Value("${jdbc.driver}")
private String driver;

@Value("${jdbc.url}")
private String url;

@Value("${jdbc.username}")
private String username;

@Value("${jdbc.password}")
private String password;

// Spring 会将当前方法的返回值以指定名称存储到 Spring 容器当中
@Bean("dataSource")
public DataSource getDataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
return dataSource;
}
}

测试

public class TestMain {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
}

Spring 集成 Junit

步骤

  1. 导入 Spring 集成 Junit 的坐标
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
  1. 使用 @Runwith 注解来替换原来的运行期
@RunWith(SpringJUnit4ClassRunner.class)
  1. 使用 @ContextConfiguration 指定配置文件或配置类
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration(classes = {SpringConfiguration.class})
  1. 使用 @Autowired 注入需要测试的对象
@Autowired
private UserService userService;
  1. 创建测试方法进行测试
@Test
public void test1() {
userService.save();
}

示例

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {

@Autowired
private UserService userService;

@Test
public void test1() {
userService.save();
}
}

Spring ContextLoaderListener

导入 spring-web 坐标

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>

配置上下文对象

使用 WebApplicationContextUtils 来获得应用上下文对象 ApplicationContext

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

使用

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();

WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService bean = app.getBean(UserService.class);
bean.save();
}