一、Spring IOC/DI
1. Spring IOC容器的介绍:简单来说,就是将程序中通过new关键字创建对象的过程,交由spring来处理。
其实创建一个对象的过程并不复杂?那么为什么我们要将这个过程交给我们的框架来处理。
原因是为了降低程序的耦合性。
2. DI:Denpendency Injection,依赖注入。
对于下面这段代码
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
如果我们用最原始的方法:我们需要自己在程序中调用方法进行赋值,例如student.setName('张三');采用依赖注入之后,spring会帮我们做这个过程,在程序中我们是看不到这段代码的。这就是依赖注入。
3. 经过控制翻转与依赖注入以后,最终我们拿到的是一个已经对属性赋值过的对象。
4. applicationContext.xml
<bean id = "category" class = "com.how2java.pojo.Category">
<property name = "name" value = "category 1"></property>
</bean>
5. TestSpring.java
package com.how2java.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.how2java.pojo.Category;
import com.how2java.pojo.Product;
public class TestSpring {
public static void main(String[] args){
// 加载核心配置文件
ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
// 获取对象且该对象的name属性已经被赋值为category1,既可以直接拿来使用
Category c = (Category)context.getBean("category");
System.out.println(c.getName());
}
}
6. 程序运行结果
7. 练习:使使用IOC的方式,获取一个Product对象
applicationContext.xml
<bean id = "product" class = "com.how2java.pojo.Product">
<property name = "name" value = "苹果"></property>
<property name = "price" value = "7"></property>
</bean>
二、Spring注入对象
Product.java
public class Product {
private int id;
private String name;
private Category category;
}
因为属性中包含一个Category对象,因此在编写spring的配置文件时,在创建Product对象时,需要利用ref引入一个外部的bean。
<bean id = "category" class = "com.how2java.pojo.Category">
<property name = "name" value = "category 1"></property>
</bean>
<bean id = "product" class = "com.how2java.pojo.Product">
<property name = "name" value = "product1"></property>
<property name = "category" ref = "category"></property>
</bean>
且ref中的值必须与第一个bean标签中的id的值相匹配。
执行结果:
三、Spring 注解方式 IOC/DI
1. 采用注解的方式将Category注入Product中,即我们不再使用上面的ref = "category"来注入。
<context:annotation-config/>
表示采用注解的方式进行配置。
@Autowired
private Category category;
仍然能运行出结果,表示使用注解方式注入成功!
2. 在setCategory()方法前加入注解
同上,也可以运行出结果
3. 使用Resource()进行注入
@Resource(name = "category")
private Category category;
4. 注意:以上均是对于对象中属性也为对象时的注入,因此,在配置文件中我们实际上是保留了bean标签的;那么针对整个bean对象而言,我们也可以采用注解的方式来进行创建,因此,我们的配置文件中连bean标签都不会存在了。只存在下面这么一句话。
<context:component-scan base-package="com.how2java.pojo"></context:component-scan>
意思是:我们所有的bean都存放在com.how2java.pojo这个包下面,在扫描的时候需要到这个包下面去扫描。
四、setter注入和构造器注入
- setter注入:其实就是spring通过配置文件的<property>元素来实现的。
即<property>元素可以为JavaBean的Setter方法传参,就是将属性值赋值给Setter方法的形参。
因此,如果我们想用setter方法进行注入的话,我们的类中必须创建了set()方法。
反映在配置文件上就是如下格式:
<bean id = "user" class = "com.how2java.pojo.User">
<property name = "name" value = "无语"></property>
<property name = "age" value = "30"></property>
<property name = "sex" value = "女"></property>
</bean>
- 构造器注入:顾名思义,就是通过我们的类的构造方法进行注入。
因此,要想通过构造器来进行注入,首先类中必须有存在参数的构造方法;其次,就是我们的配置文件。
配置文件形如以下的格式:
<bean id = "user" class = "com.how2java.pojo.User">
<constructor-arg>
<value>无语</value>
</constructor-arg>
<constructor-arg>
<value>30</value>
</constructor-arg>
<constructor-arg>
<value>女</value>
</constructor-arg>
</bean>
<constructor-arg>是<bean>元素的子元素,通过<constructor-arg>元素的<value>子元素可以为构造方法传参。
注意:书上有解释,上面设置参数的顺序与类中属性的顺序是一致的,如果不同,会出现参数错位的情况。
- 对how2java中的Category采用setter方式注入
<bean id = "category" class = "com.how2java.pojo.Category">
<property name = "name" value = "文学"></property>
</bean>
- 对how2java中的Category采用构造器方式注入
public Category(int id, String name) {
this.id = id;
this.name = name;
}
<bean id = "category" class = "com.how2java.pojo.Category">
<constructor-arg>
<value>1</value>
</constructor-arg>
<constructor-arg>
<value>运动器材</value>
</constructor-arg>
</bean>
五、DAO模式
DAO模式——Data Access Object(数据访问对象)。
提供了一种读写数据库中数据的一种方法。通过接口提供对外服务,程序的其他模块通过这些接口来访问数据库。
接口的好处就是它非常的稳定。
在Spring中利用DAO模式在tb_user表中添加数据
User.java
package com.how2java.pojo;
public class User {
private Integer id;
private String name;
private Integer age;
private String sex;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public User(Integer id, String name, Integer age, String sex) {
super();
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
public User() {
super();
}
}
UserDAO.java
package com.how2java.dao;
import com.how2java.pojo.User;
public interface UserDAO {
//添加用户信息的方法
public void insertUser(User user);
}
UserDAOImpl.java
DataSource:操作数据库的数据源对象,通过它可以创建一个数据库连接对象以建立与数据库的连接。
对于这个对象,Spring在javax.sql.DataSource提供了接口的实现,只需在Spring的配置文件中完成相关配置即可。
package com.how2java.dao.impl;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.how2java.dao.UserDAO;
import com.how2java.pojo.User;
public class UserDAOImpl implements UserDAO{
private DataSource dataSource;
public DataSource getDataSource(){
return dataSource;
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
//向数据表tb_user中添加数据
@Override
public void insertUser(User user) {
String name = user.getName();
Integer age = user.getAge();
String sex = user.getSex();
Connection conn = null;
Statement stmt = null;
try {
conn = dataSource.getConnection();
stmt = conn.createStatement();
String sql = "insert into tb_user(name,age.sex) values(" + name + "," + age + "," + sex + ")";
stmt.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
applicationContext.xml
首先定义一个JavaBean名为"DataSource"的数据源,它是Spring中的DriverManagerDataSource类的实例。
注意观察在userDAOImpl中是如何注入DataSource属性值的。(通过<ref/>标签)
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 配置数据源 -->
<bean id = "dataSource" class = "org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name = "driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>admin</value>
</property>
</bean>
<!-- 为UserDAOImpl注入数据源 -->
<bean id = "userDAOImpl" class = "com.how2java.dao.impl.UserDAOImpl">
<property name="dataSource">
<ref local = "dataSource"/>
</property>
</bean>
</beans>
需要注意在为UserDAOImpl注入数据源时,class那里需要具体写到哪一个类,否则会报ClassNotFoundException错误。
test.java
package com.how2java.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.how2java.dao.impl.UserDAOImpl;
import com.how2java.pojo.User;
public class Test {
public static void main(String[] args){
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = new User();
user.setName("张三");
user.setAge(new Integer(30));
user.setSex("男");
UserDAOImpl userDAOImpl = (UserDAOImpl)factory.getBean("userDAOImpl");
userDAOImpl.insertUser(user);
System.out.println("数据添加成功!!!");
}
}
运行结果:
但是由于没有手动提交事务,因此数据库中并没有出现新的数据。
六、 JdbcTemple操作数据库
JdbcTemplate类是Spring的核心类之一,该类在内部已经处理数据库资源的建立和释放,并可以避免一些常见的错误,如关闭连接及抛出异常,因此使用JdbcTemplate类简化了编写JDBC时所需的基础代码。
JdbcTemplate类的实例化:
- 可以直接通过数据源的引用实例化,然后在服务中使用;
- 也可以通过依赖注入的方式在ApplicationContext中产生并作为JavaBean的引用给服务使用
<!-- 配置JdbcTemplate -->
<bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref local = "dataSource"/>
</property>
</bean>
AddUser.java
package com.how2java.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class AddUser {
public static void main(String[] args){
DriverManagerDataSource ds = null;
JdbcTemplate jtl = null;
//获取配置文件
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
jtl = (JdbcTemplate)factory.getBean("jdbcTemplate"); //获取jdbcTemplate
String sql = "insert into tb_user(name,age,sex) values('小明',23,'男')";
int count = jtl.update(sql); //执行添加操作
if(count > 0){
System.out.println("添加成功!");
}else{
System.out.println("添加失败!");
}
}
}
很明显,上述JdbcTemplate的实例化是上面的第二种方式。
使用JdbcTemplate执行数据库的插入操作时,我感觉连我们定义的UserDAO和UserDAOImpl都没有用到。
控制台:
数据库:
使用JdbcTemplate向数据库中插入数据时,会自动提交事务。
七、Spring与MyBatis的整合
在how2j上面的教程中,没有指出我们需要配置log4j.properties。
但是这个是一定要加上的,且名字是固定了,不能自己更改,否则就会报错。
applicationContext.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" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:annotation-config />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>admin</value>
</property>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="typeAliasesPackage" value="com.how2java.pojo" />
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:com/how2java/mapper/*.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.how2java.mapper"/>
</bean>
</beans>
log4j.properties
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.how2java=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
运行结果: