SpringFramework系统架构
Data Access:数据访问
Data Integration:数据集成
Web:Web开发
Aop:面向切面编程
Aspects:Aop的实现
Core Container:核心容器
Test:单元测试与集成测试
核心概念
IoC/DI
IoC(控制反转):对象的创建控制权转移到外部
DI(依赖注入):在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
IoC容器
Sprig提供了一个容器,称为IoC容器,用来充当IoC思想的“外部”
Bean
IoC容器负责对象的创建、初始化等一系列工作。被创建或被管理的对象在IoC容器中统称为Bean
IoC入门案例
1、导入Spring文件
2、配置bean标签
id属性给bean起名字,id不能重复
class属性表示bean的定义类型
<bean id="bookDao" class="com.example.dao.Impl.BookDaoImpl"/> <bean id="bookService" class="com.example.service.Impl.BookServiceImpl"/>
3、获取IoC容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
4、获取bean
BookDao bookDao = (BookDao)ac.getBean("bookDao");
DI入门案例
5、删除业务层中的new对象
private BookDao bookDao;
6、提供对应的set方法
public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; }
7、配置server与dao的关联
使用property标签
name属性表示配置哪一个具体的属性
ref表示属性参照哪一个bean
<bean id="bookService" class="com.example.service.Impl.BookServiceImpl"> <property name="bookDao" ref="bookDao"></property> </bean>
Bean
Bean配置
1、为bean起别名
使用name属性,多个别名可以使用逗号、空格、分号分隔
<bean id="bookDao" name="bookDao2 bookDao3" class="com.example.dao.Impl.BookDaoImpl"/>
2、bean的作用范围
使用scope属性,默认为singletion单例模式
prototype非单例
<bean id="bookService" class="com.example.service.Impl.BookServiceImpl" scope="singleton">
Bean的实例化
构造方法
配置一个可访问的构造方法(无参构造方法)
无参构造方法如果不存在,将抛出异常BeanCreateionException
public BookDaoImpl() { System.out.println("book dao constructor is running ...."); }
静态工厂
创建一个工厂类,类中创建返回对象的静态方法
使用factory-method属性指定工厂类中的方法
public static OrderDao getOrderDao(){ System.out.println("factory setup...."); return new OrderDaoImpl(); }
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
实例工厂
创建一个工厂类
第一个bean指定工厂类、第二个bean指定方法
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/> <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
FactoryBean实现
创建类实现FactoryBean接口
public class UserDaoFactoryBean implements FactoryBean<UserDao> { //代替原始实例工厂中创建对象的方法 public UserDao getObject() throws Exception { return new UserDaoImpl();} public Class<?> getObjectType() { return UserDao.class;} }
Bean的生命周期
生命周期过程
初始化容器:1、创建对象;2、执行构造方法;3、执行属性注入(set);4、执行bean初始化方法
使用bean:执行业务操作
关闭/销毁容器:执行bean销毁方法
配置格式
使用init-method属性和destory-method属性指定方法
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
接口实现
实现InitializingBean和DisposableBean接口
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean { public void destroy() throws Exception { System.out.println("service destroy"); } public void afterPropertiesSet() throws Exception { System.out.println("service init"); } }
依赖注入
setter注入
引用类型提供set方法
简单类型配置使用property标签value属性注入
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <property name="connectionNum" value="100"/> <property name="databaseName" value="mysql"/> </bean>
构造器注入
注入标签换为constructor-arg
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <!--根据构造方法参数位置注入--> <constructor-arg index="0" value="mysql"/> <constructor-arg index="1" value="100"/> </bean>
自动装配
使用autowire属性:byType按类型(相同类型的bean唯一)、byName按名称(set方法名称)
只能对引用类型
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
集合注入
对应集合使用对应标签
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> <!--数组注入--> <property name="array"> <array> <value>100</value> <value>200</value> <value>300</value> </array> </property> <!--list集合注入--> <property name="list"> <list> <value>itcast</value> <value>itheima</value> <value>boxuegu</value> <value>chuanzhihui</value> </list> </property> <!--set集合注入--> <property name="set"> <set> <value>itcast</value> <value>itheima</value> <value>boxuegu</value> <value>boxuegu</value> </set> </property> <!--map集合注入--> <property name="map"> <map> <entry key="country" value="china"/> <entry key="province" value="henan"/> <entry key="city" value="kaifeng"/> </map> </property> <!--Properties注入--> <property name="properties"> <props> <prop key="country">china</prop> <prop key="province">henan</prop> <prop key="city">kaifeng</prop> </props> </property> </bean>
容器
加载配置文件
1、加载类路径下的配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("");
2、从文件系统下加载配置文件
ApplicationContext ctx = new FileSystemXmlApplicationContext("");
获取Bean
1、使用名称获取
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
2、使用bean的名称,并指定类型
BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
3、使用bean类型获取(同一类型的bean只能有一个)
BookDao bookDao =ctx.getBean(BookDao.class);
延迟加载
使用lazy-init属性,将值设置为true
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" lazy-init="true"/>
容器总结
BeanFactory是所有容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
ApplicationContext接口是Spring容器的核心接口,初始化bean时立即加载
ApplicationContext接口常用的实现类
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
注解开发定义bean
使用@Component定义bean
如果不指定名称,使用根据类型来获取bean
@Component("bookDao") public class BookDaoImpl implements BookDao { }
配置扫面组件加载bean
<context:component-scan base-package="com.itheima"/>
Spring提供了@Component注解的三个衍生注解
@Controller:用于表现层bean定义
@Service:用于业务层bean定义
@Repository:用于数据层bean定义
三者与@Component功能完全相同,只是名称不同
纯注解开发
将配置文件更换为配置类
@Configuration @ComponentScan("com.itheima") public class SpringConfig { }
@Configuration指定为配置类
@ComponentScan指定要扫描的包,如果多个包,添入集合
容器对象获取
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
作用范围使用@Scope注解
@Component("bookDao") @Scope("prototype") public class BookDaoImpl implements BookDao { }
生命周期
@PostConstruct
@PostConstruct public void init(){ System.out.println("init"); }
@PreDestory
@PreDestroy public void destroy(){ System.out.println("destroy"); }
依赖注入
@Autowried注解按类型自动装配
使用按名称装配使用@Qualifier注解指定名称
可以省略set方法
提供无参构造方法
@Autowired @Qualifier("bookDao") private BookDao bookDao;
使用@Value进行简单类型注入
@Value("dashadiao") private String name;
加载外部properties文件在配置类使用@PropertySource
如果有多个文件使用集合形式传入
@Configuration @ComponentScan("com.itheima") @PropertySource("jdbc.properties") public class SpringConfig { }
管理第三方bean
1.定义一个方法获得要管理的对象
2.添加@Bean,表示当前方法的返回值是一个bean
@Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/softoa"); ds.setUsername("root"); ds.setPassword("123456789"); return ds; }
配置类使用@Import导入第三方配置类
@Configuration @Import({JdbcConfig.class}) public class SpringConfig { }
注入简单类型使用@Value
注入引用类型使用形参
@Bean public DataSource dataSource(BookDao bookDao){ DruidDataSource ds = new DruidDataSource(); return ds; }
AOP
AOP简介
AOP:面向切面编程
作用:在不惊动原始设计的基础上为其进行功能增强
连接点:程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量
在SpringAOP中,理解为方法的执行
切入点:匹配连接点的式子
在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
通知:在切入点处执行的操作,共性功能
在SpringAOP中,以方法形式呈现
通知类:定义通知的类
切面:描述通知与切入点的对应关系
AOP入门案例
1、导入坐标(pom.xml)
<groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version>
2、制作连接点方法
public void save() { System.out.println("-----------------"); System.out.println("book dao save ..."); } public void update(){ System.out.println("book dao update ..."); }
3、制作共性功能
public class MyAdvice { public void method(){ System.out.println("-----------------"); } }
4、定义切入点
使用@Pointcut注解
public class MyAdvice { @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt(){} public void method(){ System.out.println("-----------------"); } }
5、绑定切入点与通知关系
@Component @Aspect public class MyAdvice { @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt(){} @Before("pt()") public void method(){ System.out.println("-----------------"); } }
@Configuration @ComponentScan("com.itheima") @EnableAspectJAutoProxy public class SpringConfig { }
AOP的工作流程
1、Spring容器启动
2、读取切面配置中的切入点
3、初始化bean,判定bean对应的类方法是否匹配任意切入点
匹配失败,创建对象
匹配成功,创建原始对象的代理对象
4、获取bean执行方法
获取bean,调用方法执行,完成操作
获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作
AOP切入点表达式
1、语法格式
动作关键字(访问修饰符 返回值 包名.类名.方法名(参数)异常名)
2、通配符
*:单个独立的任意符号
..:多个连续的任意符号
+:专用于匹配子类型
3、书写技巧
AOP通知类型
1、前置通知
@Before("pt()") public void before(){ System.out.println("前置通知"); }
2、后置通知
@After("pt()") public void after(){ System.out.println("后置通知"); }
3、环绕通知
@Around("pt()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("环绕通知1"); //原始操作调用 Object ret = pjp.proceed(); System.out.println("环绕通知2"); return ret; }
4、返回后通知
使用@AfterReturning
5、抛出异常后通知
使用@AfterThrowing
AOP通知获取数据
获取参数:所有通知
通知传入JoinPoint参数
@Before("pt()") public void before(JoinPoint jp){ System.out.println(Arrays.toString(jp.getArgs())); System.out.println("前置通知"); }
环绕通知直接使用ProceedingJoinPoint参数
获取返回值:环绕通知、返回后通知
Object ret = pjp.proceed();
获取异常:环绕通知、抛出异常后通知
Object ret = pjp.proceed();
事务
事务简介
事务作用:在数据层保障一系列的数据库操作同步
添加事务步骤
1、在方法或类上添加@Transactional
2、设置事务管理器
@Bean public PlatformTransactionManager transactionManager(DataSource dataSource){ DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); return transactionManager; }
3、开启注解式事务驱动
@EnableTransactionManagement
事务角色
事务管理员:发起事务方,通常指业务层开启事务的方法
事务协调员:加入事务方,通常指数据层方法
事务相关配置
相关属性配置
事务传播行为