文章目录
一.Spring配置数据源
1.数据源(连接池)的作用
-
数据源(连接池)是提高程序性能如出现的
-
事先实例化数据源,初始化部分连接资源
-
使用连接资源时从数据源中获取
-
使用完毕后将连接资源归还给数据源
常见的数据源(连接池):DBCP、C3P0、BoneCP、Druid
2.数据源的使用步骤
① 导入数据源的坐标和数据库驱动坐标
② 创建数据源对象
③ 设置数据源的基本连接信息
④ 使用数据源获取连接资源和归还连接资源
我们可以手动创建数据源,也可以委托让Spring帮我们创建
下面先来演示一下手动创建数据源
3.手动创建Druid数据源
首先导入坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
然后按照步骤进行
public class TestDataSource {
@Test
public void testDruid(){
//创建数据库连接池对象
DruidDataSource ds = new DruidDataSource();
//配置基本连接信息
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql:///jdbc");
ds.setUsername("root");
ds.setPassword("root");
DruidPooledConnection connection = null;
try {
//从连接池中获取连接
connection = ds.getConnection();
System.out.println(connection);
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
com.mysql.jdbc.JDBC4Connection@693fe6c9
获取连接成功,打印地址
手动创建数据源,这里连接参数直接在代码中配置,程序耦合度较高,我们可以创建properties或ResouceBundle对象用于装载连接信息,进行解耦,提高程序的独立性,这里不再撰述,下面将演示用Spring来获取数据源并进行解耦
4.通过Spring创建Druid数据源
4.1.配置Bean以及用getBean获取数据源
<bean id="DataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///jdbc"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
public void testDruidBySpring(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
DruidDataSource ds = (DruidDataSource) applicationContext.getBean(DruidDataSource.class);
try {
DruidPooledConnection conn = ds.getConnection();
System.out.println(conn);
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
com.mysql.jdbc.JDBC4Connection@906d29b
成功输出
另外,我们注意到,通过Spring容器创建Datasource对象,这里连接信息配置在Spring的xml文件中,也成功进行了解耦。但如果我们想更进一步的提高程序的独立性,我们可以将基本连接信息抽取到properties文件中。
4.2. 抽取jdbc连接信息配置文件
在xml使用properties需要引入另外一个命名空间,以免与默认命名空间混淆。
引入context命名空间和约束路径:
命名空间:xmlns:context=“http://www.springframework.org/schema/context”
约束路径:http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
然后使用el表达式关联配置
<?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
">
<!--加载外部的properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--使用el表达式加载properties里的配置-->
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.host}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
public void testDruidBySpring(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
DruidDataSource ds = applicationContext.getBean(DruidDataSource.class);
try {
DruidPooledConnection conn = ds.getConnection();
System.out.println(conn);
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
输出结果表明可以正常获取连接
com.mysql.jdbc.JDBC4Connection@146587a2
二.Spring注解开发
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,另外,注解开发才是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
1. 起步
使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean 需要进行扫描以便识别使用注解配置的类、字段和方法。
<context:component-scan base-package="venture.study"></context:component-scan>
这里配置扫描venture.study包下的
2. 原始注解
注解 | 说明 | 其它 |
---|---|---|
@Component | 使用在类上用于实例化Bean | 为了加强程序可读性,可以使用下面三种注解 |
@Controller | 使用在web层类上用于实例化Bean | 对Component的语义化 |
@Service | 使用在service层类上用于实例化Bean | 对Component的语义化 |
@Repository | 使用在dao层类上用于实例化Bean | 对Component的语义化 |
@AutoWired | 使用在字段上用于根据类型依赖注入1 | 有相同类型的bean会报错2 |
@Qualifier | 结合@Autowired一起使用用于根据名称进行依赖注入1 | |
@Resource3 | 相当于@Autowired+@Qualifier,按照名称进行注入1 | |
@Value | 注入普通属性 | 一般结合properties使用进行解耦 |
@Scope | 标注Bean的作用范围 | |
@PostConstruct | 使用在方法上标注该方法是Bean的初始化方法 | |
@PreDestroy | 使用在方法上标注该方法是Bean的销毁方法 |
-
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
-
如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
-
如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
-
如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
另外,该注释依赖于javax.annotation.Resource,jdk1.8及以下才有自带。若是9版本及以上,可以从pom中导入,否则无法注入,导致运行时要注入的对象找不到,直接报空指针异常
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
示例:
//Service层
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("好家伙")
private String str;
@Value("18")
private int age;
/*@Autowired
@Qualifier("userDao")*/
@Resource(name="userDao")
private UserDao userDao;
public void run() {
System.out.println(str);
System.out.println(age);
userDao.run();
}
//@Component("userDao")
@Repository("userDao")
@Scope("singleton")
public class UserDaoImpl implements UserDao{
public void run() {
System.out.println("run方法执行了");
}
}
//模拟视图层
public class AnnoController {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.run();
}
}
好家伙
18
run方法执行了
3. 新注解
使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:
- 非自定义的Bean的配置:
<bean>
- 加载properties文件的配置:
<context:property-placeholder>
- 组件扫描的配置:
<context:component-scan>
- 引入其他文件:
<import>
注解 | 说明 | 其它 |
---|---|---|
@Configuration | 用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解 | |
@ComponentScan | 用于指定 Spring 在初始化容器时要扫描的包。 作用和在 Spring 的 xml 配置文件中的 一样 | 相当于context:component-scan,在配置类上用 |
@Bean | 使用在方法上,标注将该方法的返回值存储到 Spring 容器中 | |
@PropertySource | 用于加载.properties 文件中的配置 | 相当于context:property-placeholder |
@Import | 用于导入其他配置类 | 可以以数组形式导入多个配置类 |
//核心配置类
@Configuration
@ComponentScan("venture.study")
@Import({DataSourceConf.class})
public class SpringConf {
}
//bean配置类
@PropertySource("classpath:jdbc.properties")
public class DataSourceConf {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.host}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name="dataSource")
public DataSource getDataSource() throws PropertyVetoException {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driverClassName);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
//测试类
@Test
public void test() throws SQLException {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConf.class);
DataSource dataSource = (DataSource)
applicationContext.getBean("dataSource");
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
注意到这里使用AnnotationConfigApplicationContext()加载核心配置类来创建Spring容器,这时我们可以直接删除applicationContext.xml配置文件,因为配置已经可以完全使用注解替代
输出结果
com.mysql.jdbc.JDBC4Connection@3ce3db41
注意:properties里的配置信息数据库用户名的key取username会与mysql关键字冲突,这里为了避免冲突加上了前缀jdbc.
三.Spring集成Junit
我们使用原始Junit测试Spring的时候,每次都必须先在家Spring容器然后通过getBean获取对象。这对于频繁的测试来说是非常不方便的。
在测试类中,每个测试方法都必须有以下两行代码
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
为了减少代码冗余,我们可以
-
让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
-
将需要进行测试Bean直接在测试类中进行注入
1.起步
1)导入SpringJunit包4以及Junit包
2)使用@Runwith注解替换原来的运行期
3)使用@ContextConfiguration指定配置文件或配置类
4)使用@Autowired注入需要测试的对象
5) 创建测试方法进行测试
@RunWith(SpringJUnit4ClassRunner.class)//Spring测试单元替换原来的要运行期 @ContextConfiguration(classes = {SpringConf.class})//加载spring核心配置类 public class SpringJunitTest { @Autowired private UserService userService; @Test public void testUserService(){ userService.run(); } }
输出结果:
好家伙
18
run方法执行了
注:本例是加载的配置类,如要加载spring核心配置文件 用@ContextConfiguration(value = {“classpath:applicationContext.xml”})
四.Spring集成Web环境
1.ApplicationContext应用上下文获取方式
应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的,但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) 。这样的弊端是配置文件加载多次,应用上下文对象创建多次。
在Web项目中,可以使用ServletContextListener监听Web应用的启动。在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到web最大的域servletContext域中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了
2.使用Spring提供的应用上下文获取工具
Spring提供了一个监听器ContextLoaderListener就是对上述功能的封装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象。 所以我们需要做的只有两件事:
① 在web.xml中配置ContextLoaderListener监听器(记得在maven中导入spring-web坐标)
<!--全局参数-->
<context-param>
<param-name>contextConfigLocation</param-name><!--webApplicationContextUtils工具类通过该全局参数名获取配置文件-->
<param-value>classpath:applicationContext.xml</param-value><!--Spring配置文件名直接在此更改即可-->
</context-param>
<!--加入Spring的监听器-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!--url映射servlet-->
<servlet>
<servlet-name>WebApplicationContextUtilsTest</servlet-name>
<servlet-class>venture.study.web.WebApplicationContextUtilsTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WebApplicationContextUtilsTest</servlet-name>
<url-pattern>/getwebcontext</url-pattern>
</servlet-mapping>
② 使用WebApplicationContextUtils获得应用上下文对象ApplicationContext
public class WebApplicationContextUtilsTest extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ApplicationContext applicationContext =
WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());//需要ServletContext对象的传入
UserService userService = (UserService)applicationContext.getBean("userService");
userService.run();
}
}
访问/getwebcontext,控制台输出结果:
UserDao的run方法执行了