前言
近几年,技术市场对新人越来越不友好,社招几乎是三年经验起步。所以很多人都说能走校招千万别走社招,年初我企图走社招,然后绝望了 = =。还是要抓紧每一秒,多学习多练习。
目录
- 环境搭建
- 入门
- 配置详解
- AOP
- JDBCTemplate
- 事务
- 整合 Web 和 Junit
- SSH 整合
正文
1. 环境搭建
这里介绍的是 Spring Framework。
导包
根据需要选择手动导入 jar 包,或者用依赖管理工具。
- 下载
官网目前好像没提供直接下载,可以去 maven 仓库下载 - Gradle
列举了一些常用的,更多详情参考 官网dependencies { // 核心包 compile 'org.springframework:spring-context:4.3.8.RELEASE' // 可选包 compile 'org.springframework:spring-tx:4.3.8.RELEASE' compile 'org.springframework:spring-web:4.3.8.RELEASE' compile 'org.springframework:spring-orm:4.3.8.RELEASE' compile 'org.springframework:spring-aspects:4.3.8.RELEASE' compile 'org.springframework:spring-test:4.3.8.RELEASE' }复制代码
2. 入门
IOC
定义
控制反转(Inverse of Control):对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。
这里是指将对象创建的任务交给 Spring 来做。
Demo
com/ittianyu/spring/a_ioc/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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="UserDao" class="com.ittianyu.spring.a_base.z_common.dao.impl.UserDaoImpl"/>
</beans>复制代码
com.ittianyu.spring.a_base.a_ioc.TestClass
public class TestClass {
@Test
public void helloIOC() {
String xmlPath = "com/ittianyu/spring/a_ioc/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 通过 spring 创建 dao
UserDao userDao = (UserDao) applicationContext.getBean("UserDao");
userDao.save(new User("hello spring !"));
}
}复制代码
DI
定义
依赖注入(Dependency Injection,简称DI):在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。
在这里指的是 要创建的对象中的成员变量由 Spring 进行 set。
Demo
com/ittianyu/spring/b_di/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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="UserService" class="com.ittianyu.spring.a_base.z_common.service.impl.UserServiceImpl">
<!-- 依赖注入 DI:在创建 service 时,需要设置 service 所依赖的 dao 实现 -->
<property name="userDao" ref="UserDao"/>
</bean>
<bean id="UserDao" class="com.ittianyu.spring.a_base.z_common.dao.impl.UserDaoImpl"/>
</beans>复制代码
com.ittianyu.spring.a_base.b_di.TestClass
public class TestClass {
@Test
public void helloDI() {
String xmlPath = "com/ittianyu/spring/b_di/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 通过 spring 创建 service
UserService userService = (UserService) applicationContext.getBean("UserService");
userService.addUser(new User("hello spring !"));
}
}复制代码
3. 配置详解
实例化方式
默认构造、静态工厂、实例工厂
默认构造
通过默认构造方法实例化对象
<bean id="" class="">复制代码
静态工厂
通过工厂的静态方法实例化对象
<bean id="" class="工厂全类名" factory-method="静态方法">复制代码
工厂
通过工厂的普通方法实例化对象
<!-- 1. 创建工厂实例 -->
<bean id="myBeanFactory" class="com.xxx.MyBeanFactory"></bean>
<!-- 2. 通过工厂实例创建对象 userservice
* factory-bean 指定工厂实例
* factory-method 指定创建方法
-->
<bean id="userService" factory-bean="myBeanFactory"
factory-method="createService"></bean>复制代码
Bean 种类
- 普通 bean:通过默认构造直接创建的 bean
- FactoryBean:具有工厂生产对象能力的 bean,只能生成特定的对象。
bean 必须使用 FactoryBean接口,此接口提供方法getObject()
用于获得特定 bean。<bean id="" class="FB">
先创建FB实例,使用调用 getObject() 方法,并返回方法的返回值FB fb = new FB(); return fb.getObject();复制代码
- BeanFactory 和 FactoryBean 对比?
- BeanFactory:工厂,用于生成任意bean。
- FactoryBean:特殊bean,用于生成另一个特定的bean。 例如:ProxyFactoryBean ,此工厂bean用于生产代理。<bean id="" class="....ProxyFactoryBean"> 获得代理对象实例。AOP使用
作用域
类别 | 说明 |
---|---|
singleton | Spring IOC 容器中仅存在一份 bean 实例 |
prototype | 每次都创建新的实例 |
request | 一次 http 请求创建一个新的 bean,仅适用于 WebApplicationContext |
session | 一个 session 对应一个 bean 实例,仅适用于 WebApplicationContext |
globalSession | 一般用于 Portlet 应用环境,作用域仅适用于 WebApplicationContext 环境 |
scope 为作用域
<bean id="" class="" scope="">复制代码
生命周期
初始化和销毁
目标方法执行前后执行的方法
<bean id="" class="" init-method="初始化方法" destroy-method="销毁方法">复制代码
例子:
com.ittianyu.spring.a_base.e_lifecycle.UserServiceImpl
public class UserServiceImpl implements UserService{
@Override
public void addUser() {
System.out.println("addUser");
}
// 在 xml 中配置声明周期方法
public void onInit() {
System.out.println("onInit");
}
// 销毁方法只有满足 1.容器 close 2. 必须是单例
public void onDestroy() {
System.out.println("onDestroy");
}
}复制代码
配置:
com/ittianyu/spring/a_base/e_lifecycle/applicationContext.xml
...
<!-- 注册 初始化和销毁方法 -->
<bean id="UserService" class="com.ittianyu.spring.a_base.e_lifecycle.UserServiceImpl"
init-method="onInit" destroy-method="onDestroy" />
...复制代码
测试:
com.ittianyu.spring.a_base.e_lifecycle.TestClass
public class TestClass {
@Test
public void test() {
String xmlPath = "com/ittianyu/spring/e_lifecycle/applicationContext.xml";
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 通过 spring 生成工厂 调用 工厂方法 生成对象
UserService userService = applicationContext.getBean("UserService", UserService.class);
userService.addUser();
// 关闭容器才会调用 销毁的方法
applicationContext.close();
}
}复制代码
BeanPostProcessor
只要实现此接口BeanPostProcessor,并配置此 bean,则在所有初始化方法前执行 before()
,在初始化方法之后执行 after()
。
例子:
com.ittianyu.spring.a_base.e_lifecycle.MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
// 不在 before 使用代理因为 jdk 的代理是面向接口,而 init 和 destroy 方法是 实现类的
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("before");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("after");
// 在 after 中生成 代理对象,在执行方法前后开启和关闭事务
Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务");
Object result = method.invoke(bean, args);
System.out.println("关闭事务");
return result;
}
});
return proxy;
}
}复制代码
com/ittianyu/spring/a_base/e_lifecycle/applicationContext.xml
...
<!--注册 初始化 前后回调-->
<bean class="com.ittianyu.spring.a_base.e_lifecycle.MyBeanPostProcessor" />
...复制代码
属性注入
注入方式
- 手动装配:一般进行配置信息都采用手动
- 基于xml装配:构造方法、setter方法
- 基于注解装配
- 自动装配:struts 和 spring 整合可以自动装配
- byType:按类型装配
- byName:按名称装配
- constructor:构造装配
- auto: 不确定装配
构造注入
实体类
public class User {
private Integer id;
private String username;
private Integer age;
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
// 省略 get set...
}复制代码
配置
...
<!--
基于 name 配置构造参数,不常用
-->
<!-- <bean id="user" class="com.ittianyu.spring.a_base.f_xml.a_constructor.User">
<constructor-arg name="username" value="name"/>
<constructor-arg name="age" value="1"/>
</bean>-->
<!--
基于 index 和 type 方式
如果不指定 type,可能匹配到多个符合条件的构造方法,默认使用位置在前面的那个
-->
<bean id="User" class="com.ittianyu.spring.a_base.f_xml.a_constructor.User">
<constructor-arg index="0" type="java.lang.Integer" value="1"/>
<constructor-arg index="1" type="java.lang.String" value="hello"/>
</bean>
...复制代码
set 注入
实体类省略
...
<!--
利用 setter 方法进行参数注入
property 的值可以利用 内嵌标签来完成,但一般很少用
-->
<bean id="Person" class="com.ittianyu.spring.a_base.f_xml.b_setter.Person">
<property name="name" value="Jone" />
<property name="age">
<value