一:Spring并天下
1:Spring帝国:
①:Spring崛起
什么是Spring:
源于Rod Johnson在其著作《Expert one on one J2EE design and development》中阐述的部分
理念和原型的衍生而来.Spring是一个轻量级的DI/AOP容器的开源框架,致力于构建轻量级的JavaEE应用,简化应用
开发,本身涵盖了传统应用开发还拓展到移动端,大数据领域.
什么是容器(Container):
从程序设计角度看就是装对象的对象,因为存在放入,拿出等操作,所以容器还是要管理对象的生命周期,如
Tomcat就是Service和JSP的容器.
Spring提供了JavaEE每一层的解决方案(full stack) .Spring其实就是全栈式框架.
![Spring与SpringMVC的框架整合](https://img-blog.csdn.net/20180404200433463?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
②:Spring的优势:
Spring除了不能帮我们写业务逻辑,其余的几乎什么都能帮助我们简化开发.
①:Spring能帮我们低侵入/低耦合地根据配置文件创建及相关对象之间的依赖关系.
②:Spring面向切面编程能帮我们无耦合的实现日志记录,性能统计,安全控制等.
③:Spring能非常简单的且强大的声明式事务管理.
④:Spring提供了与第三方数据访问框架(如:Hibemate,JPA)无缝集成,且自己也提供了一套JDBC模板来方便数据库访问.
⑤:Spring提供与第三方Web(如Struts1/2,JSF)框架无缝集成,且自己也提供了一套Spring MVC框架来方便Web层搭建.
⑥:Spring能方便的与Java Mail,任务调度,缓存框架等技术整合,降低开发难度.
③:Spring帝国
Spring主要产品:
Spring FrameWork:
Spring帝国之核心,其他Spring其他产品都是基于Spring框架而来.
Spring Boot:
Spring Boot 是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用
的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而是开发人员不在需要定义样板化的配置.
Spring Cloud:Spring cloud微服务框架,为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,
控制总线,一次性token,全居锁,leader选举,分布式session,集群状态)中快速构建的工具,使用Spring Cloud的
开发者可以快速的启动服务或构建应用,同时能够快速和云平台资源进行对接.
Spring Cloud Data Flow:
Spring Cloud Data Flow简化了专注于数据流处理的应用程序的开发和部署.通过
SpringBoot启动应用,采用Spring Cloud Stream,Spring Cloud Task完成微服务构建.
官网的推荐组合:Spring Boot + Spring Cloud + Spring Cloud Data Flow
![Spring的其他主要项目版图](https://img-blog.csdn.net/20180404203728808?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
④:Spring基石
![Spring基石,了解一下就行,框住的是我们需要学习的](https://img-blog.csdn.net/20180404204632103?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
⑤:Spring框架包
Spring框架包包含两大部分:
1:spring-framework-5.X.RELEASE:Spring核心组件(必须).
docs: Spring开发,帮助文档.
libs: Spring 核心组件的,jar包,源代码,文档.
schema: Spring配置文件的schema约束文件.
2:spring-framework-3.0.5.RELEASE-dependencies:
Spring依赖的第三方组件(根据需要拷贝),包含了各大开源组织提供的依赖jar,比如日志库,AOP联盟库,连接池库等.
建议使用meve来下载jar包,不需要拷贝jar包了.
⑥:STS工具
Eclipse: STS工具 Spring Tool Suite基于Eclipse的开发工具.
IDEA: 后面会录制一套IDEA的视频.
2:Spring基础
①:Ioc和DI思想
IoC: Inversion of Control(控制反转):读作"翻转控制",更好理解,不是什么技术,而是一种设计思想,
好比于MVC.就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理.
正控:若调用者需要使用某个对象,其自身就得负责该对象及该对象所依赖对象的创建和组装.
反控:调用者只管负责从Spring容器中获取需要使用的对象,不关心对象的创建过程,也不关心该对象依赖对象的
创建以及依赖关系的组装,也就是把创建对象的控制权翻转给了Spring框架.
DI: Dependency Injection (依赖注入)从字面上分析: IoC:指将对象的创建权,翻转给了Spring容器: DI:指Spring
创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设置值给该对象.
IoC 从字面意义上很难体现出谁来维护对象之间的关系,Martin Fowler提出一个新的概念--DI,更明确描述了"被注入对象(service对象)
依赖IoC容器来配置依赖对象(DAO对象)".
②:HelloWord程序
依赖jar:
spring-beans-版本.RELEASE.jar
spring-core-版本.RELEASE.jar
报错再添加:
com.springsource.org.apache.commons.logging-1版本.jar
开发jar包
1:准备jar包
2:开发HelloWorld程序
3:在applicationContext.xml中完成配置(如何获取xsd声明)
4:启动Spring容器
5:从容器中获取指定名称的bean
6:调用bean的方法
什么是BeanFactory:
BeanFactory是Spring最古老的接口,表示Spring IoC容器--生产bean对象的工厂,负责配置,创建和管理bean
什么是Bean: 被Spring Ioc容器管理的对象称之为bean.
Spring Ioc容器如何知道哪些是它管理的对象:
此时需要配置文件:Spring Ioc容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配.
元数据的配置有三种方式(后讲):
1:XML-based configuration
2:Annotation-based configuration
3:Java-bean configuration
Spring IoC管理bean的原理:
1:通过Resource对象加载配置文件
2:解析配置文件,得到指定名称的bean
3:解析bean元素,id作为bean的名字,class用于反射得到bean实例:
注意:此时,bean类必须存在一个无参数构造器(和访问权限无关);
4:调用getBean方法的时候,从容器中返回对象实例;
结论:就是把代码从JAVA文件中转移到XML中.
③:getBean方法的三种签名
//使用Spring框架之后
@Test
public void test2() throws Exception {
HelloWorld world = null;
//---------------------------------
//1:从classpath路径去寻找资源问价,创建资源对象
Resource resource = new ClassPathResource("applicationContext.xml");
//2:根据资源对象,创建Spring IoC容器对象
BeanFactory factory = new XmlBeanFactory(resource);
//3:从Spring IoC容器中获取指定名称(helllo world)对象
//签名一:Object getBean(String beanName);//根据bean对象在容器中的名称来取
//world = (HelloWorld) factory.getBean("HelloWorld");
//签名二: T getBean(Class requiredType)//按照指定的类型去寻找bean对象
//world = factory.getBean(HelloWorld.class);
//签名三: T getBean(String name, @Nullable Class requiredType)根据bean的类型+ID名称去寻找,推荐的
world = factory.getBean("HelloWorld",HelloWorld.class);
//---------------------------------
world.sayHello();
}
④:Eclipse提示XML语法
XML需要导入schema约束,约束指向网络路径:
方式一:连网后,自动缓存路径文件到本地,提供提示功能;
方式二:无连网,需要配置xsd schema文件位置(操作如下图);
①:到解压spring/schemas/beans/spring-bean.xsd.
②:选择schema location方式.
③:复制网络路径 http://www.springframework.org/schema/beans/spring-beans.xsd
⑤:Spring基本配置
id="helloWorld" class="cn.wolfcode.hello.HelloWorld"/>
name跟id 以后只需要用id属性就行,表示的意思一样,但是name元素可以用空格隔开不同的名字
""/>元素
在开发中,随着应用规模的增加,系统中元素配置的数量也会增加,导致applicationContext.xml配置
文件变得非常臃肿,为了提高其可读性,我们可以将一个applicationContext.xml文件分解成多个配置文件,
然后在applicationContext.xml文件中包含其他配置文件即可.
语法如下: "classpath:cn/wolfcode/hello/hello.xml"/>
使用import元素注意:
1:默认情况下:从classpath的根路径寻找.
2:可以使用前缀来定位文件的基础位置:
①:[classpath:] 后面的文件从classpath路径开始找(推荐);
②:[file]:后面的文件使用文件系统的路径开始找;
注意:只有当框架中实现了Resource接口才能够识别上诉的前缀标识符.
⑥:Spring测试框架
测试依赖:
Spring-test-版本.RELEASE.jar
Spring-context-版本.RELEASE.jar
Spring-aop-版本.RELEASE.jar
Spring-expression-版本.RELEASE.jar
//使用Junit4的测试案例
//运行Spring的jUnit4
@RunWith(SpringJUnit4ClassRunner.class)
//上下文配置对象,寻找配置文件的
//@ContextConfiguration("classpath:cn/wolfcode/spring_test/springtext.xml")
@ContextConfiguration//默认从测试了路径找 测试类名-context.xml文件
public class SpringTestTest {
//表示自动按照类型从Spring容器中找到bean对象,并设置给该字段
@Autowired
private SomeBean bean;
@Test
public void test() throws Exception {
bean.doWork();
}
}
//使用Junit5方式的测试
@SpringJUnitConfig
public class SpringTestTest{
@Autowired
private SomeBean bean;
@Test
void testName(){
bean.doWork();
}
}
二: 帝国之剑 IoC
1:IoC
①:IOC容器
1:SpringIoC容器(Contaner):
BeanFactory: Spring 最底层的接口,只提供了IoC功能,负责创建,组装,管理Bean,在应用中,一般不使
用BeanFactory,而推荐使用ApplicationContext(应用上下文).
ApplicationContext:接口继承了BeanFactory,除此之外还提供AOP集成,国际化处理,事件传播,统一资源加载等功能.
2:Bean的创建时机(此时不使用Spring Test):
①:BeanFactory需要等到获取某一个bean的时候才会创建bean--延迟初始化.
②:ApplicationContext在启动Spring容器的时候就会创建所有的bean(Web应用建议).
bean属性中的lazy-init="true"也可以延迟初始化,也可以设置到到schema上面的default-lazy-init="true"
/**
结论:BeanFactory有延迟初始化的特点,在创建Spring容器的时候,不会立马去创建容器中管理的Bean对象
而是要等到从容器中去获取对象的时候,才去创建对象.
*/
//使用BeanFactory
@Test
public void testBeanFactory() throws Exception {
Resource resource = new ClassPathResource("cn/wolfcode/container/ContainerTest-Context.xml");
BeanFactory factory = new XmlBeanFactory(resource);
System.out.println("====================");
Person person = factory.getBean("person",Person.class);
System.out.println(person);
}
/**
结论:在创建Spring容器的时候,就会把容器中管理的bean马上初始化,而不会等到获取bean的时候才去初始化.
*/
//使用ApplicationContext
@Test
public void test2() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/wolfcode/container/ContainerTest-Context.xml");
System.out.println("============================");
Person person = ctx.getBean("person",Person.class);
System.out.println(person);
}
②:bean实例化方式:
①:构造器实例化(无参数构造器),最标准,使用最多. (使用比较多)
②:静态工厂方法实例化:解决系统遗留问题
③:实例工厂方法实例化:解决系统遗留问题
④:实现FactoyrBean接口实例化:实例工厂变种,如集成MyBatis框架使用: (使用比较多)
org.mybatis.spring.SqlSessionFactoryBean
<bean id="cat1" class="cn.wolfcode.createbean._01_constructor.Cat1"/>
<bean id="cat2" class="cn.wolfcode.createbean._02_static_factory.Cat2Factory"
factory-method="createInstance"/>
<bean id="cat3" class="cn.wolfcode.createbean._03_instance_factory.Cat3Factory"/>
<bean id="getcat3" factory-bean="cat3" factory-method="createInstance"/>
<bean id="dat4" class="cn.wolfcode.createbean._04_factory_bean.Cat4Factory">
<property name="username" value="你好">property>
bean>
③:bean的作用域:
在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围
"" scope="作用域"/>
singleton: 单例,在Spring IoC容器中仅存在一个Bean实例 (默认的scope)
proptotype: 多例,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean();不会再容器启动时创建对象
request: 用于web开发,将Bean放入request范围,request.setAttribute("xxx")在调用一个request获得同一个Bean
session:用于web开发,将Bean放入Session范围,在同一个 Session获得同一个Bean
globalSession:一般用于Porlet应用环境,分布式系统存在全局session概念(单点登录),如果不是porlet环境.
globalSession 等同于Session
Spring5开始出现:websocket, globalSession作废.
在开发中主要使用 scope="singleton" scope="prototype"
总结: 对于Struts1中的Action使用request, Struts2中的Action使用prototype类型,其他使用singleton
④:bean初始化和销毁
init-method: 定义初始化方法,在构造器执行之后,立马执行
destroy-method: 定义销毁之前的方法,在销毁执行之前,调用
scope: 设置为"prototype" 不是 单例设计模式, 他不知道你啥时候调用完,所以就不关闭资源 考虑资源来之不易,不易轻易释放
"ds" class="cn.wolfcode.lifecycle.MyDataSource" scope="singleton"
init-method="open" destroy-method="close"/>
此方法在Spring测试类可用
如果使用ApplicationContext来创建对象,就得手动关闭资源
@Test
public void testName1() throws Exception {
@Cleanup
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("cn/wolfcode/lifecycle/App-Context.xml");
MyDataSource ds = ctx.getBean("ds",MyDataSource.class);
ds.doWork();
}
三种关闭资源方法:最后加 ds.close(); @Clearup; ctx.registerShutdownHook();
⑤:bean的实例化过程(生命周期)
bean的生命周期: bean从出身--消亡直接的整个过程
BeanFactory: 延迟初始化特点
ApplicationContext: 在启动Spring容器的时候,就会去创建bean对象
![bean的生命周期](https://img-blog.csdn.net/2018040512541723?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![bean的生命周期2](https://img-blog.csdn.net/20180405125513373?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![bean的生命周期3](https://img-blog.csdn.net/20180405132714642?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
2: DI
①:通过XML配置装配
DI:Dependency Injection(依赖注入)
从字面上分析:IoC:指对象的创建权,反转给了Spring容器;
DI:指Spring创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设值给该对象.
什么是注入操作? setter方法 构造器
注入值的类型:
1):常量值(简单类型):value元素
2):对象 : ref元素
3):集合 : 对应集合类型元素
通过XML配置装配(不推荐)
id="dog" class="" autowire="byType" /> autowire: byName byType constructor no
②:setter注入
注入常量 注入对象 注入集合 跟上面注入方法一样
<bean id="employee" class="cn.wolfcode.di_setter.Employee1">
<property name="name" value="will">property>
<property name="age" value="17">property>
<property name="salary" value="5000">property>
bean>
<bean id="cat1" class="cn.wolfcode.di_setter.Cat1">bean>
<bean id="person" class="cn.wolfcode.di_setter.Person1" >
<property name="c1" ref="cat1">property>
bean>
<bean id="collectionBean1" class="cn.wolfcode.di_setter.CollectionBean1">
<property name="set">
<set>
<value>set1value>
<value>set2value>
set>
property>
<property name="list">
<list>
<value>list1value>
<value>list2value>
list>
property>
<property name="array">
<array>
<value>array1value>
<value>array2value>
array>
property>
<property name="map">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value="value2"/>
map>
property>
<property name="prop">
<value>
p1=v1
p2=v2
p3=v3
value>
property>
bean>
③:构造器注入
把上面的property换成constructor-arg 即可
<bean id="person2" class="cn.wolfcode.di_constructor.Person2" >
<constructor-arg name="c2">
<bean class="cn.wolfcode.di_constructor.Cat2"/>
constructor-arg>
bean>
④:bean元素的继承
多个bean元素共同配置的抽取,实则是bean配置的拷贝,和Java的继承不同.
<bean id="base" abstract="true">
<property name="name" value="will">property>
<property name="age" value="19">property>
bean>
<bean id="someBean1" class="cn.wolfcode.bean_tag_inheritance.SomeBean1" parent="base">
<property name="weight" value="500">property>
bean>
<bean id="someBean2" class="cn.wolfcode.bean_tag_inheritance.SomeBean2" parent="base">
<property name="age" value="99">property>
<property name="color" value="业楼">property>
bean>
⑤:配置数据库连接池
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
@Autowired
private DataSource ds;
@Test
public void testName() throws Exception {
/*ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/springdemo");
ds.setUsername("root");
ds.setPassword("111111");
ds.setInitialSize(2);*/
@Cleanup
Connection conn = ds.getConnection();
@Cleanup
PreparedStatement ps = conn.prepareStatement("SELECT * FROM student");
@Cleanup
ResultSet rs = ps.executeQuery();
while(rs.next()){
System.out.print(rs.getLong("id")+",");
System.out.print(rs.getString("name")+",");
System.out.println(rs.getInt("age")+",");
}
}
}
⑥:property-placeholder
<context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close" >
<property name="driverClassName" value="${jdbc.driverClassName}">property>
<property name="url" value="${jdbc.url}">property>
<property name="username" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
<property name="initialSize" value="${jdbc.initialSize}">property>
bean>
⑦:模拟用户注册的例子
查看我的Eclipse代码,利用xml配置的方式回顾了IoC跟DI.
domain
@Setter@ToString@Getter
public class User {
private Long id;
private String name;
private int age;
}
dao
public interface IUserDAO {
void save(User u);
}
impl
public class IUserDAOImpl implements IUserDAO{
@Setter
private DataSource ds;
@SneakyThrows
public void save(User u){
System.out.println("保存操作");
@Cleanup
Connection conn = ds.getConnection();
String sql = "INSERT INTO user (name,age) values (?,?)";
@Cleanup
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,u.getName());
ps.setInt(2, u.getAge());
ps.executeUpdate();
}
}
service
public interface IUserService {
void register(User user);
}
impl
public class UserServiceImpl implements IUserService{
private IUserDAO dao;
public void setDao(IUserDAO dao) {
this.dao = dao;
}
@SneakyThrows
public void register(User user){
System.out.println("注册操作");
dao.save(user);
}
}
action
//模拟Struts2的Action/SpringMVC的Controller
public class UserAction {
@Setter
private IUserService service;
public String execute() throws Exception{
System.out.println("注册请求");
service.register(new User());
return "success";
}
}
app
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
@Autowired
private UserAction userAction;
@Test
public void testRegister() throws Exception {
userAction.execute();
}
}
app-Context.xml
<context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}">property>
<property name="url" value="${jdbc.url}">property>
<property name="username" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
<property name="initialSize" value="${jdbc.initialSize}">property>
bean>
<bean id="userdao" class="cn.wolfcode.register.dao.impl.IUserDAOImpl">
<property name="ds" ref="dataSource">property>
bean>
<bean id="UserService" class="cn.wolfcode.register.service.impl.UserServiceImpl">
<property name="dao" ref="userdao">property>
bean>
<bean id="userAction" class="cn.wolfcode.register.action.UserAction" scope="prototype">
<property name="service" ref="UserService" >property>
bean>
3:使用注解配置
①:DI注解
Autowired和Qualifier注解
Spring规范提供
1:可以让Spring自动的把属性的对象找出来,并注入到对象.
2:可以贴在字段或者setter方法上面
3:可以同时注入多个对象
@Autowired
public void setter(OtherBean otherBean,OtherBean other2){}
4:可以注入一些Spring内置的重要对象,比如BeanFactory,ApplicationContext,ServiceContext等;
5:默认情况下Autiwrired注解必须要能找到对应的对象,否则报错.
通过required=false来避免这个问题:@Autowired(required=false)
6:第三方程序:Spring3.0之前,需要手动配置Autowired注解的解析程序:
在Web开发中必须配置
7:Autowired注解寻找bean的方法:
1):首先按照依赖对象的类型找,如果找到,就是用setter或者字段直接注入
2):如果Spring上下文中找到多个匹配类型,再按照名字去找,如果没有 匹配报错;
3):可以通过使用@Qualifier("name")标签来规定依赖对象按照bean的id和类型的组合方式去找;
Resource
DI注解:
Spring官方: Autowired
JavaEE规范: Resource
共同点: 都需要配置DI注解解析器:
不同点: Resource注解必须要能找到对应的对象,否则报错.
Resource注解首先按照名字去找,如果找到,就使用setter或者字段注入;
如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错;
Resource可以直接使用name属性指定bean的名称(@Resource(name="名字"));但是
如果指定的name,就只能按照name去找如果找不到,就不再按照类型去找
Value
注入:
常量类型: value Value
对象类型: ref Autowired/Resource
@Value("${service.port}")
private int port;
<context:property-placeholder location="classpath:db.properties,classpath:server.properties"/>
②:IoC注解
Component注解和其stereotype注解
//注解配置:@Component
@Component("myDataSource")//组件如果不写value属性值,此时bean的id默认是类型首字母小写;
public class MyDataSource {
}
<context:component-scan base-package="cn.wolfcode.ioc"/>
bean组件版型:四个组件的功能是相同的,只是用于标注不同类型的组件.
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注.
@Repository用于标注数据访问组件,即DAO组件.
@Service用于标注业务层组件.
@Controller用于标注控制层组件(如struts中的Ation,SpringMVC的Controller).
他们几个的功能跟component功能其实是一模一样的.优先使用下面3种注解,当不属于其他组件再使用component
③:Scope 和 PostConstruc 以及 PreDestroy 注解
@PostConstruct用于贴在初始化方法上
@PreDestroy用于贴在销毁方法上
@Component
@Scope("singleton")
public class SomeBean {
public SomeBean(){
System.out.println("构建SomeBean对象");
}
@PostConstruct//构建对象之后
public void open(){
System.out.println("初始化方法");
}
@PreDestroy//销毁之前
public void close(){
System.out.println("销毁前扫尾方法");
}
public void doWork(){
System.out.println("工作");
}
}
之后记得写IoC注解解析器
package="cn.wolfcode.lifecycle"/>
④:使用注解完成注册案例
注意:
使用注解并不能完全取代XML的配置
比如配置连接池DruiDataSource,我们就不能到这个类中去贴注解.
JavaConfig + 注解
@setter注解贴在字段上面仅仅是为我们生成一个Setter方法,本身不能完成注入操作.
@Autowired注解贴在字段上面,自动从Spring 容器中去找到匹配的对象,并设置给该字段.
IoC和DI其实是一个东西:
IoC:字面上,更多强调的是Spring帮我们创建对象.
DI:字面上,Spring不仅帮我们创建对象,还要为该对象设置依赖的数据.
最后学会用XML与注解完成注册案例配置
domain
@Setter@ToString@Getter
public class User {
private Long id;
private String name;
private int age;
}
dao
public interface IUserDAO {
void save(User u);
}
impl
@Repository
public class IUserDAOImpl implements IUserDAO{
@Autowired
private DataSource ds;
@SneakyThrows
public void save(User u){
System.out.println("保存操作");
@Cleanup
Connection conn = ds.getConnection();
String sql = "INSERT INTO user (name,age) values (?,?)";
@Cleanup
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,u.getName());
ps.setInt(2, u.getAge());
ps.executeUpdate();
}
}
service
public interface IUserService {
void register(User user);
}
impl
@Service
public class UserServiceImpl implements IUserService{
@Autowired
private IUserDAO dao;
@SneakyThrows
public void register(User user) {
System.out.println("注册操作");
dao.save(user);
}
}
action
@Component//变现层
public class UserAction {
@Autowired
private IUserService service;
public String execute() throws Exception{
System.out.println("注册请求");
service.register(new User());
return "success";
}
}
APP
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
@Autowired
private UserAction userAction;
@Test
public void testRegister() throws Exception {
userAction.execute();
}
}
APP-context.xml
<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:annotation-config/>
<context:component-scan base-package="cn.wolfcode"/>
<context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}">property>
<property name="url" value="${jdbc.url}">property>
<property name="username" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
<property name="initialSize" value="${jdbc.initialSize}">property>
bean>
beans>