Spring次日笔记java
学习基于注解的IoC配置,你们脑海里首先得有一个认知,即注解配置和xml配置要实现的功能都是同样的,都是要下降程序间的耦合。只是配置的形式不同。mysql
关于实际的开发中到底使用xml仍是注解,每家公司有着不一样的使用习惯。因此这两种配置方式咱们都须要掌握。web
基于注解配置的方式也已经逐渐代替xml。因此咱们必需要掌握使用注解的方式配置Spring。spring
注意:Eclipse须要先安装了STS插件,或者使用STS开发工具建立项目。sql
注意:在基于注解的配置中,咱们还要多拷贝一个aop的jar包。以下图:数据库
|
|
注意:基于注解整合时,Spring配置文件导入约束时须要多导入一个context名称空间下的约束session
<?xml version="1.0" encoding="UTF-8"?>app <beans xmlns="http://www.springframework.org/schema/beans"框架 xmlns:p="http://www.springframework.org/schema/p"dom 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 "> </beans> |
建立一个测试的服务类,而且加入使用@Component注解,声明该类容许注入到Spring容器
package com.zj.spring.service;
import org.springframework.stereotype.Component;
//1.使用注解配置,须要将启动是就建立对象的类表示为组件类 @Component public class CustomerService {
public void save(){ System.out.println("-保存数据-"); }
}
|
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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">
<!-- 声明扫描包以及子包的类。若是发现有组件注解的类,就建立对象,并加入到容器 --> <context:component-scan base-package="cn.zj.spring"></context:component-scan> </beans> |
package com.zj.spring.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zj.spring.service.CustomerService;
public class CustomerServiceTest {
public static void main(String[] args) { //CustomerService cs=new CustomerService(); ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
CustomerService customerService = context.getBean("customerService",CustomerService.class); customerService.save(); context.close(); } }
|
--测试结果,若是能够调用服务方法,测试成功
|
默认状况下, 被注解@Component 扫描的类的名称就是当前类名的首字母小写名称,开发者能够自定义组件的名称
/* 使用注解方式配置IOC @Component 说明当前类被Spring管理,Spring框架启动的时候就会建立此类的对象 设置当前Bean的名称 默认当前Bean的名称就是简单类名的 首字母小写 customerService value 属性能够自定义组件的名称 等价于 <bean id/name="bean名称"> @Component(value="service") 简写,能够省略value @Component("service")
*/ @Component("service") public class CustomerService { public void save() { System.out.println("-保存数据-"); } } |
咱们将用于被扫描建立对象的注解,统称为组件注解。
组件包括:@Component,@Controller,@Service,@Repository。
组件注解的功能都是标识类为注解的组件类,启动Spring框架的程序时,声明将这些组件类注入到Spring容器里面。意味着,只有加了这四个注解任何一个注解的类,在程序启动的时候,Spring就经过配置文件指定的路径将该路径下的全部带组件注解的类建立对象而且放在容器里面。
功能相似原来配置文件的<bean>标签
问题:明明一个@Component注解就能够知足了扫描的须要,为何要有四个呢?
答:其实Spring初版注解的实现(spring 2.5),就是使用一个@Component。从3.0之后,做者认为根据分层的须要,把它拆成了四个。为了可让开发人员,可见便可得,一看到注解,当即知道类的性质。因此分红了四个
@Controller:用于声明表示层的组件注解
@Service:用于声明服务层的组件注解
@Repository:用于声明持久层的组件注解
@Component:用于声明三层之外的组件注解
问题:那么,这四个注解交换使用会报错吗。如:持久层,我放@Service标记。
答:处理@Controller在SpringMVC里面有强制的要求,SpringMVC的表示层必须使用@Controller组件注解。其余状况,用乱了是不会报错的,不过咱们必须不能用乱。不遵照规范,否则别人没法跟你一块儿开发了。
Xml配置须要配置对象的做用范围
<bean id="someBean" class="..." scope="做用范围"></bean> |
若是使用注解配置bean,那么bean的做用范围也须要使用注解配置
@Scope("做用范围")
singleton
|
单例 ,在Spring IoC容器中仅存在一个Bean实例 (默认的scope) |
prototype |
多例 ,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,至关于执行new XxxBean(): |
request |
用于web开发,将Bean放入request范围 ,request.setAttribute("xxx") , 在同一个request 得到同一个Bean
|
session |
用于web开发,将Bean 放入Session范围,在同一个Session 得到同一个Bean |
package cn.zj.spring.controller;
import javax.annotation.Resource;
import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller;
import cn.zj.spring.service.CustomerService; @Controller("customerController") @Scope("prototype") public class CustomerController {
//直接字段注入,不须要setter方法 //@Resource //按照类型注入 @Resource(name="customerService")//类型+id private CustomerService customerService;
public void save() { //调用服务的save方法 customerService.save(); } }
|
在开发中主要使用 scope="singleton"、 scope="prototype"
对于MVC中的Action/Controller使用prototype类型,其余使用singleton
在xml配置中能够配置对象的初始化方法和销毁方法
<bean id="someBean" class="cn.zj.spring.domain.SomeBean" init-method="init" destroy-method="destory"></bean> |
若是使用注解配置bean,那么bean的做用范围也须要使用注解配置
@PostConstruct // 至关于<bean init-method="init" /> public void init() { System.out.println("初始化方法执行了"); } @PreDestroy// 至关于<bean destroy-method="destory" /> public void destory() { System.out.println("销毁方法执行了"); } |
回顾:XML配置文件使用<property name=”” ref=””>实现注入的。经过注入注解也能够实现。
Spring提供了两套注解能够解决依对象依赖注入的方案
1,@Autowired +@Qualifier():是Spring定义的标签
2,@Resouce:是J2EE的规范
@Autowired注解:用于给引用注入容器的对象。
(1) 首先按照依赖对象的类型找,若是找到则使用setter方法或者字段直接注入;
(2) 若是在Spring上下文中找到多个匹配的类型,再按照名字去找,若是没有匹配则报错;
(3) 能够经过使用@Qualifier("otherBean")标签来规定依赖对象按照bean的id+类型去找
使用@Autowired注入的三种状况
package cn.zj.spring.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;
import cn.zj.spring.service.CustomerService; //表示层使用@Controller //若是组件注解不声明对象名,默认使用默认命名法, //所谓的默认命名就是,将类的首字符小写做为类的对象名 //组件注解 //属性 value:做用用于指定该类对象的自定义对象名 @Controller("customerController") public class CustomerController {
//直接字段注入,不须要setter方法 @Autowired private CustomerService customerService;
/*public void setCustomerService(CustomerService customerService) { this.customerService = customerService; }*/ public void save() { //调用服务的save方法 customerService.save(); } }
|
package cn.zj.spring.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;
import cn.zj.spring.service.CustomerService;
//表示层使用@Controller //若是组件注解不声明对象名,默认使用默认命名法, //所谓的默认命名就是,将类的首字符小写做为类的对象名 //组件注解 //属性 value:做用用于指定该类对象的自定义对象名 @Controller(value="customerController") public class CustomerController {
private CustomerService customerService=null;
//注意,若是将@Autowired方法方法上面,意思就是将对象注入到该的方法的参数 //意味着:Spring会自动根据参数的CustomerService类型匹配容器中对应的对象给它 //注意:可以使用@Autowired注解的方法是必须有参数的 @Autowired public void setCustomerService(CustomerService customerService) { //问题:加了@Autowired的方法在启动的时候是否执行了? //答:若是该方法没有执行,那么this.customerService的对象从哪里来呢? //加了@Autowired在启动项目的时候是必须自动执行的 System.out.println("-setCustomerService已经被执行-"); this.customerService = customerService; }
public void save(){ System.out.println("-保存客户-CustomerAction"); customerService.save(); }
}
|
package cn.zj.spring.controller;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller;
import cn.zj.spring.service.CustomService;
@Controller public class CustomController {
private CustomService service;
/* * 方式三 : 构造器注入 * 使用注解的IOC建立bean的状况下 * 默认bean中有什么样的构造器,spring就调用那个构造器去建立对应的bean对象 * 而且会自动注入 构造器中对应类型参数的对象 * * 问题: 若是构造函数的参数类型对应的bean有多个,会抛出异常 * org.springframework.beans.factory.NoUniqueBeanDefinitionException 不是惟一的bean异常 * 解决方案: 在参数前面 使用 @Qualifier("service1") 注解 * 从多个bean 获取指定 id 对应的bean便可 */ public CustomController(@Qualifier("service1") CustomService service) { this.service = service; }
public void save() { service.save(); }
}
|
@Qualifier注解:用于指定注入的对象名,使用@Autowired注入对象时,@Autowired没有指定对象名的属性,只能经过@Qualifier字段容器中对象名
属性
value:指定注入Spring容器中对应对象名的对象给引用。
@Controller("customerController") public class CustomerController {
//直接字段注入,不须要setter方法 @Autowired @Qualifier(value="customerService") private CustomerService customerService;
public void save() { //调用服务的save方法 customerService.save(); } } |
@Resource注解是Spring框架支持Sun官方制定的JSR-250标准注入对象的实现。
JSR-250就是Sun公司制定,对注入的对象的标准。
@Resource 功能等同 @Autowired + @Qualifier ,等同配置文件标签 <proprty name=”...” ref=”...”>
@Resource注解:用于给引用注入容器的对象,能够经过name属性指定对象名
注意事项:@Resource只能使用字段和setter方法,不能注入构造方法
package cn.zj.spring.controller;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import cn.zj.spring.service.CustomerService; @Controller("customerController") public class CustomerController {
//直接字段注入,不须要setter方法 //@Resource //按照类型注入 @Resource(name="customerService")//类型+id private CustomerService customerService;
public void save() { //调用服务的save方法 customerService.save(); } }
|
除了@Resource注解是Java官方的标准,内置在JDK里面之外,Spring内置实现的注解声明放在spring-beans-5.0.5.RELEASE.jar里面。以下图所示:
|
<value>
//value只能设置,标量类型=基础数据类型+包装类+String
@Value注解:注入基本数据类型以及它们的包装类和String类型数据的,支持${}注入Properties文件的键值对,等同 <proprty name=”...” value=”${Key}”>。
属性:
value:注入基本数据类型和String类型数据的
package cn.zj.spring.dao.impl;
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository;
import cn.zj.spring.dao.UserDao; import cn.zj.spring.pojo.User;
@Repository public class UserDaoImpl implements UserDao {
/** * @Value(value="") * 能够从Spring容器读取 .properties 配置文件内容 * value :配置文件的对应的key -->使用 ${key} 获取 * 程序运行中自动将 properties 对应key的获取出来设置给字段 * */
//等价 <property name="driverClassName" value="${jdbc.driverClassName}"> @Value("${jdbc.driverClassName}") private String driverClassName;
@Value("${jdbc.url}") private String url;
@Value("${jdbc.username}") private String username;
@Value("${jdbc.password}") private String password;
//@Value("${jdbc.maxActive}") @Value("100") //开发者也手动赋值 private String maxActive;
@Override public void insert(User user) { System.out.println(driverClassName); System.out.println(url); System.out.println(username); System.out.println(password); System.out.println(maxActive);
} }
|
//@Component("userDao") @Repository("userDao") public class UserDaoImpl implements UserDao { @Override public void insert(User user) { System.out.println("注册的Dao方法执行"); } } |
@Service("userService") public class UserServiceImpl implements UserService {
/*@Autowired @Qualifier("userDao")*/
@Resource(name="userDao") private UserDao dao;
@Override public void register(User user) { dao.insert(user); } //由于要用 public void setDao(UserDao dao) { this.dao = dao; } } |
@Controller public class UserController { /*@Autowired @Qualifier("userService")*/ @Resource(name="userService") private UserService service;
public void register(User user) {
service.register(user); } } |
public class UserServletTest {
@Test public void testSpring() throws Exception { //建立用户对象:模拟接受用户参数,封装对象的过程 User user = new User(); user.setUsername("张三"); user.setPassword("admin"); UserController controller = context.getBean("userController",CustomerController.class); //执行注册操做 controller.register(user); } } |
配置文件(只须要配置一个包扫描便可)
<!-- 配置包扫描 cn.zj.spring : 此包以及子包所有被扫描 --> <context:component-scan base-package="cn.zj.spring"/> |
咱们发现,之因此咱们如今离不开xml配置文件,是由于咱们有一句很关键的配置:
<!-- 告知spring框架在,读取配置文件,建立容器时,扫描注解,依据注解建立对象,并存入容器中 -->
<context:component-scan base-package="cn.zj.spring"></context:component-scan>
若是他要也能用注解配置,那么咱们就能够脱离xml文件了。
经过@Configuration注解和@ComponentScan注解
替换XML配置文件的 @Configuration注解
|
@Configuration配置类注解,在纯注解配置中,类加了该注解,就意味着该类是Spring的配置类。该类的功能就是用于替代原来的XML配置文件。
做用: 用于指定当前类是一个spring配置类,当建立容器时会从该类上加载注解。获取容器时须要使用AnnotationConfigApplicationContext(有@Configuration注解的类.class)。
|
@ComponentScan注解
|
@ComponentScan注解扫描类,做用就是配置扫描Spring组件类的路径。功能等同原来配置文件的 --做用: 用于指定spring在初始化容器时要扫描的包。做用和在spring的xml配置文件中的: <context:component-scan base-package="cn.zj.spring"/>是同样的。 --属性: basePackages:用于指定要扫描的包。和该注解中的value属性做用同样。
|
@PropertySource注解
|
做用: 用于加载.properties文件中的配置。例如咱们配置数据源时,能够把链接数据库的信息写到properties配置文件中,就可使用此注解指定properties配置文件的位置。 属性: value[]:用于指定properties文件位置。若是是在类路径下,须要写上classpath:
|
@Bean注解
|
做用: 该注解只能写在方法上,使用此方法建立一个对象,而且放入spring容器。它就至关于咱们以前在xml配置中介绍的<bean标签>
属性: name:给当前@Bean注解方法建立的对象指定一个名称(即bean的id)。
|
@Import注解
|
做用: 用于导入其余配置类,在引入其余配置类时,能够不用再写@Configuration注解。固然,写上也没问题。 <import > 属性: value[]:用于指定其余配置类的字节码。
|
需求:经过一个简单的入门示例,实现建立一个配置类使用@Configuration注解和@ComponentScan注解替换xml文件。
建立一个Java项目,导入必须的jar包以及编写好须要的类结构。代码目录以下:
|
--经过该配置类的代码替换掉Spring配置文件
package cn.zj.spring.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource;
import com.alibaba.druid.pool.DruidDataSource;
/* * @Configuration * 说明把当前类当作成Spring框架的配置文件 * @ComponentScan * 配置注解包扫描的位置 * @PropertySource("classpath:db.properties") * 读取.peroperties 后缀的配置文件 */
@Configuration //@ComponentScan(basePackages= {"cn.zj.spring.action","cn.zj.spring.service","cn.zj.spring.dao"}) @ComponentScan("cn.zj.spring") @PropertySource("classpath:db.properties") public class SpringConfig {
/** * @Value(value="") * 能够从Spring容器读取 .properties 配置文件内容 * value :配置文件的对应的key -->使用 ${key} 获取 * 程序运行中自动将 properties 对应key的获取出来设置给字段 * */
//等价 <property name="driverClassName" value="${jdbc.driverClassName}"> @Value("${jdbc.driverClassName}") private String driverClassName;
@Value("${jdbc.url}") private String url;
@Value("${jdbc.username}") private String username;
@Value("${jdbc.password}") private String password;
@Value("${jdbc.maxActive}") private Integer maxActive;
//<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" //init-method="init" destroy-method="close"> @Bean(name="dataSource",initMethod="init",destroyMethod="close") public DataSource getDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driverClassName); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); dataSource.setMaxActive(maxActive); return dataSource; }
}
|
package cn.zj.spring.test;
import java.sql.Connection;
import javax.sql.DataSource;
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import cn.zj.spring.config.SpringConfig;
public class SpringTest {
@Test public void testName() throws Exception {
// 1.读取 xml 配置文件,启动框架,建立Spring容器对象 //ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 1. 读取SpringConfig 类配置文件,启动动框架,建立Spring容器对象 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
//2. 获取 链接池对象 DataSource dataSource = context.getBean("dataSource", DataSource.class);
//2.1获取数据库链接对象 Connection conn = dataSource.getConnection();
System.out.println(conn); } }
|
--测试结果,输出组件类调用方法的输出值。配置成功
|
存在问题:
1,每一个测试都要从新启动Spring容器,启动容器的开销大,测试效率低下。
2,不该该是测试代码管理Spring容器,应该是Spring容器在管理测试代码。
|
|
|
Spring测试必须保证Eclipse的单元测试的最低版本是 4.12版本,若是使用的Eclipse版本很低,那么单元测试版本可能低于4.12,那么须要开发者手动导入单元测试的jar包
若是使用Spring方式测试,必须使用两个注解
@RunWith注解
表示先启动Spring容器,把junit运行在Spring容器中
@ContextConfiguration注解
从哪里加载资源文件,默认从src(源目录)下面加载
package cn.zj.spring.test;
import static org.junit.Assert.*;
import javax.annotation.Resource; import javax.swing.Spring;
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.zj.spring.config.SpringConfig; import cn.zj.spring.service.CustomerService;
//表示先启动Spring容器,把junit运行在Spring容器中 @RunWith(SpringJUnit4ClassRunner.class) //表示从哪里加载资源文件,默认从src(源目录)下面加载 @ContextConfiguration("classpath:applicationContext.xml") public class CustomerServiceTest {
@Resource ApplicationContext context;
@Test public void testSpring() throws Exception { //1.获取Spring容器对象 //AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(“applicationContext.xml”);
//2.获取CustomerController对象 CustomerService controller = context.getBean("customerService",CustomerService.class);
//执行保存方法 controller.save(); } }
|
@ContextConfiguration()
classes 属性: 读取spring的纯java配置文件
package cn.zj.spring.test;
import static org.junit.Assert.*;
import javax.annotation.Resource; import javax.swing.Spring;
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.zj.spring.config.SpringConfig; import cn.zj.spring.service.CustomerService;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=Spring.class) public class CustomerServiceTest {
@Resource ApplicationContext context;
@Test public void testSpring() throws Exception { //1.获取Spring容器对象 //AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
//2.获取CustomerController对象 CustomerService controller = context.getBean("customerService",CustomerService.class);
//执行保存方法 controller.save(); } } |
Spring对象也支持JDBC,对JDBC只进行了薄薄的一层封装
问题: Java开发已经有JDBC,为何Spring还要支持JDBC操做呢?
最重要的缘由: Spring操做JDBC能自动管理事务
|
1,建立数据库 spring_jdbc |
2.建立数据表 t_user |
CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `email` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
3.建立对应的domain对象 |
public class User { private Integer id; private String name; private String email; 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 String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", email=" + email + "]"; } public User(Integer id, String name, String email) { super(); this.id = id; this.name = name; this.email = email; } public User() { super(); // TODO Auto-generated constructor stub }
} |
4.建立DAO层 |
public class UserDaoImpl implements UserDao {
@Override public void save(User user) {
}
@Override public void delete(Integer id) { }
@Override public void update(User user) {
}
@Override public User findById(Integer id) {
return null; }
@Override public List<User> list() {
return null; } } |
5.建立Service层 |
public class UserServiceImpl implements UserService {
private UserDao dao;
@Override public void save(User user) { dao.save(user); }
@Override public void delete(Integer id) { dao.delete(id); }
@Override public void update(User id) { dao.update(id); }
@Override public User findById(Integer id) { // TODO Auto-generated method stub return dao.findById(id); }
@Override public List<User> list() { // TODO Auto-generated method stub return dao.list(); }
public void setDao(UserDao dao) { this.dao = dao; } } |
6.测试代码 |
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class UserServiceTest {
@Resource private UserService service;
@Test public void testSave() {
User user = new User(null, "乔峰", "qf@qq.com");
service.save(user); }
@Test public void testDelete() { service.delete(3); }
@Test public void testUpdate() { User user = new User(2, "段誉", "123123sdfsdf@qq.com"); service.update(user); }
@Test public void testFindById() {
User user = service.findById(1); System.out.println(user);
} @Test public void testList() {
List<User> users = service.list(); System.out.println(users); } } |
ApplicationContext.xml配置 |
<!-- 引入 db.properties配置文件 --> <context:property-placeholder location="classpath:db.properties"/>
<!-- 配置Druid链接池 : DataSource 数据源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close" > <!-- setter方法注入属性值 --> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <!-- 最大链接数 --> <property name="maxActive" value="${jdbc.maxActive}"/> </bean>
<!-- 配置DAO层 --> <bean id="userDao" class="cn.zj.spring.dao.impl.UserDaoImpl2"> <!-- setter方法注入数据源:链接池 --> <property name="dataSource" ref="dataSource"/> </bean>
<!-- 配置Service层 --> <bean id="userSercice" class="cn.zj.spring.service.impl.UserServiceImpl"> <!-- 注入dao --> <property name="dao" ref="userDao"/> </bean> |
|
|
|
Spring为各大框架提供对应的模板类能够直接操做数据库
若是使用JDBC就使用JDBCTemplate类(将数据库的基本操做方法已经封装好了,直接调用便可)
|
导入相关jar包 mysql-connector-java-5.x.jar:MySQL驱动包 spring-jdbc-5.0.5.RELEASE.jar:支持JDBC spring-tx-5.0.5.RELEASE.jar: 支持事务 druid1.9.jar 链接池 |
DAO层代码 |
// 引入JDBCTemplate 模板类 private JdbcTemplate jdbcTemplate;
//使用setter方式注入数据源便可 public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); }
@Override public void save(User user) { this.jdbcTemplate.update("insert into t_user (name,email) values (?,?)", user.getName(),user.getEmail()); }
@Override public void delete(Integer id) { this.jdbcTemplate.update("delete from t_user where id = ?",id);
}
@Override public void update(User user) { this.jdbcTemplate.update("update t_user set name = ?,email = ? where id = ?", user.getName(),user.getEmail(),user.getId()); }
@Override public User findById(Integer id) { String sql = "select * from t_user where id = ?"; User user = this.jdbcTemplate.queryForObject(sql,new Object[] {id}, new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setName(rs.getString("name")); user.setEmail(rs.getString("email")); user.setId(id); return user; } }); return user; }
@Override public List<User> list() { String sql = "select * from t_user";
List<User> users = this.jdbcTemplate.query(sql,new RowMapper<User>(){ @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setName(rs.getString("name")); user.setEmail(rs.getString("email")); user.setId(rs.getInt("id")); return user; } });
return users; }
|
问题: 每一个DAO层的实现类都写上述一样的代码,100个DAO写100次,代码重复99次
Spring考虑到这点:专门为各类持久化操做抽取了 Support父类,开发者本身的到只须要继承对应的Support类便可
public class UserDaoImpl implements UserDao { // 引入JDBCTemplate 模板类 private JdbcTemplate jdbcTemplate;
//使用setter方式注入数据源便可 public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } } |
|
JdbcDaoSupport类的结构 public abstract class JdbcDaoSupport extends DaoSupport {
@Nullable private JdbcTemplate jdbcTemplate;
/** * Set the JDBC DataSource to be used by this DAO. */ public final void setDataSource(DataSource dataSource) { if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) { this.jdbcTemplate = createJdbcTemplate(dataSource); initTemplateConfig(); } } @Nullable public final JdbcTemplate getJdbcTemplate() { return this.jdbcTemplate; } } |
让本身的类继承自JdbcDaoSupport类就解决上上述代码重复问题 |
public class UserDaoImpl2 extends JdbcDaoSupport implements UserDao {} |
Spring的IOC和DI 的配置 可使用XML配置,也能够注解配置
今日内容
注解配置
(1) @Component 通用IOC 组件,试用任意Spring对象管理
(2) @Controller 主要在表现层使用
(3) @Service 业务层使用
(4) @Repository DAO层使用
(5) 必须在xml中配置包扫描的位置
(6) <context:component-scan base-package=”cn.zj.spring”>
(1) @Autowired + @Qualifier Spring 框架提供
(2) @Resource JavaEE 官方的规范
(1) 纯注解配置替代xml配置,可是全部配置依然存在,只是配置方式变换成在类上面贴注解的形式(将来的趋势)--SpringBoot(纯注解)
(1) 为了更方便的开发Spring程序
(1) 优势 :主要可以让Spring自动控制事务
(2) JdbcTemplate 模板类 进行数据表的增删改查
(3) JdbcDaoSupport
① 优势: 将jdbcTemplate模板类的建立进行封装
② 缺点:只能在xml配置对应DAO类