spring示例--01
主要内容:bean的装配
①完全的基于xml配置
②基于配置类的
③去掉xml,完全靠注解的
1. 准备工作
1.1 数据准备:
CREATE TABLE `user` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `birthday` datetime DEFAULT NULL, `sex` varchar(10) DEFAULT NULL, `address` varchar(40) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
INSERT INTO test.user (id, name, birthday, sex, address) VALUES (1, 'name1', '1995-01-01 00:00:00', 'man', 'address1'); INSERT INTO test.user (id, name, birthday, sex, address) VALUES (2, 'name2', '1995-01-01 00:00:00', 'man', 'address2');
1.2 数据操作:使用JdbcTemplate,暂忽略事务控制
1.3 maven包:全都是4.0.0版本
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-context.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring-core.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring-beans.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring-expression.version}</version> </dependency> <!--spring aop--> <!-- <dependency>--> <!-- <groupId>org.springframework</groupId>--> <!-- <artifactId>spring-aop</artifactId>--> <!-- <version>${spring-aop.version}</version>--> <!-- </dependency>--> <!--spring jdbc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-jdbc.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-tx.version}</version> </dependency>
1.4 实体类
package xt.domain; import lombok.*; @Getter @Setter @AllArgsConstructor @NoArgsConstructor @Builder public class User { private Integer id; private String username; private String birthday; private String sex; private String address; @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}'; } }
2. 基于xml的
Dao里面通过JdbcTemplate执行sql,JdbcTemplate通过xml配置装配(构造函数注入)到Dao上
package xt.demo.dao; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.RowMapper; import xt.domain.User; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; public class UserDao { private JdbcTemplate jt; public UserDao(JdbcTemplate jt) {this.jt = jt;} public int saveUser(User user) { return jt.update("insert into user values(null,?,?,?,?)",new PreparedStatementSetter(){ @Override public void setValues(PreparedStatement ps) throws SQLException { ps.setString(1,user.getUsername()); ps.setString(2,user.getBirthday()); ps.setString(3,user.getSex()); ps.setString(4,user.getAddress()); } }); } public List<User> queryAllUser() { List<User> lists = jt.query("select * from user", new RowMapper<User>() { @Override public User mapRow(ResultSet resultSet, int i) throws SQLException { User user = new User(); user.setId(resultSet.getInt("id")); user.setUsername(resultSet.getString("name")); user.setBirthday(resultSet.getString("birthday")); user.setSex(resultSet.getString("sex")); user.setAddress(resultSet.getString("address")); return user; } }); return lists; } }
相应的配置文件:beans.xml 放在Resources的一级目录下
<?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"> <bean id="UserDao" class="xt.demo.dao.UserDao"> <constructor-arg name="jt" ref="jdbcTemplate"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource1"></property> </bean> <!--数据源--> <bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8"/> <!--注意&符号写为 & 否则解析配置文件会出错--> <property name="username" value="root"/> <property name="password" value="123"/> </bean> </beans>
测试:
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml"); UserDao userDao = ac.getBean("UserDao", UserDao.class); List<User> users = userDao.queryAllUser();
基于xml装配特点:
自由使用,比如自己写的Dao里面,要用到第三方库里的JdbcTemplate,在bean标签里面引用即可
对象很多时,bean标签也多了起来;每个要获取bean里面的对象的地方,都要先读取xml返回ApplicationContext对象
3. 基于配置类
配置类与业务逻辑无关,单独放在一个地方,只用来配置bean(通过java配置类装配而不是xml里的bean标签)
3.1 数据源和jdbc
对比2里的beans.xml,先将数据源和jdbcTemplate从xml里拿出来,用配置类来配置
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource1"></property> </bean> <!--数据源--> <bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8"/> <!--注意&符号写为 & 否则解析配置文件会出错--> <property name="username" value="root"/> <property name="password" value="123"/> </bean>
这个bean里面是一个DriverManagerDataSource对象,并通过set方法注入数据。
jdbc通过set方式注入DataSource,组装成JdbcTemplate对象(当前是单数据源)
改成配置类如下:则上面的两个bean配置可以去掉了
package xt.demo.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; @Configuration public class JdbcTemplateConfig { @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(DataSource dataSource1){ JdbcTemplate jt = new JdbcTemplate(); jt.setDataSource(dataSource1); return jt; } @Bean(name="dataSource1") public DataSource createDataSource(){ DriverManagerDataSource dmd = new DriverManagerDataSource(); dmd.setDriverClassName("com.mysql.jdbc.Driver"); dmd.setUrl("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8"); dmd.setUsername("root"); dmd.setPassword("123"); return dmd; } }
每个@Bean("")注解相当于一个<bean>标签
3.2
再配置一个配置类,里面先引入上面的数据源配置类,然后指定要扫描的包。这里也通过@Bean注解注入Dao对象,因此原来的beans.xml不需要了
package xt.demo.config; import org.springframework.context.annotation.*; import org.springframework.jdbc.core.JdbcTemplate; import xt.demo.dao.UserDao; @Configuration @ComponentScan(basePackages = {"xt.demo"}) @Import({JdbcTemplateConfig.class}) public class SpringConfig { @Bean(name="userDao") public UserDao createUserDao(JdbcTemplate jdbcTemplate){ return new UserDao(jdbcTemplate); } }
@ComponentScan相当于 <context:component-scan> 标签
3.3 测试
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); UserDao userDao = ac.getBean("userDao", UserDao.class); List<User> users = userDao.queryAllUser();
3.4 数据源配置类优化
DataSource的参数放到配置文件里去:datasource.properties 在配置类的同级目录下
mysql.driver=com.mysql.jdbc.Driver mysql.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8 mysql.username=root mysql.password=123
数据源配置类引入配置文件:
package xt.demo.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; @Configuration @PropertySource({"classpath:/xt/demo/config/datasource.properties"}) public class JdbcTemplateConfig { @Value("${mysql.driver}") private String driver; @Value("${mysql.url}") private String url; @Value("${mysql.username}") private String username; @Value("${mysql.password}") private String password; @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(DataSource dataSource1){ JdbcTemplate jt = new JdbcTemplate(); jt.setDataSource(dataSource1); return jt; } @Bean(name="dataSource1") public DataSource createDataSource(){ DriverManagerDataSource dmd = new DriverManagerDataSource(); dmd.setDriverClassName(driver); dmd.setUrl(url); dmd.setUsername(username); dmd.setPassword(password); return dmd; } }
再用3.3的测试方法测试时,DriverManagerDataSource里面报错: driver(其它的也是) 被赋值 "${mysql.driver}" 这样的字面值,而不是配置文件里面对应的值,将spring版本从4.0.0切换到5.3.1之后就没问题了。
如果一定要用4.0.0的话,只能通过另一个xml文件引入datasource.properties,如下:datasource-config.xml 注解@PropertySource("xxx.properties")改成@ImportResource("xxx.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: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 location="classpath:/xt/demo/config/datasource.properties"/> </beans>
package xt.demo.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; @Configuration //@PropertySource({"classpath:/xt/demo/config/datasource.properties"}) @ImportResource({"classpath:/xt/demo/config/datasource-config.xml"}) public class JdbcTemplateConfig { @Value("${mysql.driver}") private String driver; @Value("${mysql.url}") private String url; @Value("${mysql.username}") private String username; @Value("${mysql.password}") private String password; @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(DataSource dataSource1){ JdbcTemplate jt = new JdbcTemplate(); jt.setDataSource(dataSource1); return jt; } @Bean(name="dataSource1") public DataSource createDataSource(){ DriverManagerDataSource dmd = new DriverManagerDataSource(); dmd.setDriverClassName(driver); dmd.setUrl(url); dmd.setUsername(username); dmd.setPassword(password); return dmd; } }
这种通过配置类配置的,和xml配置的没有什么区别,基本上只是把<bean>标签替换成@Bean注解
4. 自动装配的
上面的2.基于xml配置的、3.基于配置类配置的,步骤比较多,但也比较自由,想引入哪个类就引入哪个类,如何设置属性(注入数据)可以自由配置,适用于引入第三方包(比如,上面的jdbc换成其它工具,很方便切换)
组件扫描加自动装配更为方便,但是不便于引入第三方包