一,概述
1.什么是spring?
Spring框架是轻量级的JavaEE框架,是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层,可以和其他的框架无缝整合。
Spring有两个核心部分:IOC和Aop
(1)IOC:控制反转,把创建对象的过程交给Spring进行管理
(2)Aop:面向切面,不修改源代码进行功能增强
2.Spring特点
轻量:spring是一个轻量级开发框架基于spring开发的对象不依赖于spring的API,开销小
控制反转(依赖注入):spring运用IOC,使对象依赖的其他对象会通过被动的方式传递,而不是对象自己创建
面相切片:即Aop,将业务逻辑和服务分隔开
容器:Spring 是一个容器, 因为它包含并且管理应用对象的生命周期
框架:Spring是一个从实际开发中抽取出来的框架, 因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高了企业应用的开发效率
二,基础应用
1.前期配置
①创建一个普通的java项目工程
②在lib下导入相应的jar包,其中几个包是用于测试方法
③创建applicationContext.xml配置spring约束文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd "
default-autowire="byName">
</beans>
2.IOC应用
IOC(控制反转):将创建对象的控制权由原本的程序员编写程序创建交给了springIOC容器来创建可以理解为一个容器(帮我们创建bean,管理bean)
bean标签基本属性详解:bean标签把 对象放入到spring容器中
id 属性则是在Spring容器中唯一标识符,可随意写,但建议命名为类相关的名字。
class 属性:确定该类的位置。意思是告诉Spring容器,帮我实例对象的类所在位置。
property标签:设置该类的属性的是
name 则是告诉spring容器 你要设置的该类里面的那一个属性, 后面一般 value,或者ref
value属性 是给属性一般赋值
ref则是给属性 赋引用型的值一般是另一个类的实例化对象
使用构造方法进行注入
constructor-arg 标签:
name 构造方法形参名
value:赋值
ref:赋引用对象名
1.创建对象
以前创建对象方式: new 反射 克隆 反序列化,需要我们手动new
public static void main(String[] args) {
User user=new User();
}
IOC创建对象
<bean id="u1" class="com.hqyj.gyq.entity.User">
<!--必须有无参构造-->
<!--<property>写在<bean>代表配置该bean的某个属性,name:属性名称 value:属性的值-->
<!--user类中属性的setter方法必须有-->
<property name="userId" value="2"></property>
<property name="userName" value="zs"></property>
</bean>
<!-- 或者-->
<bean id="u1" class="com.hqyj.gyq.entity.User" autowire="byType">
<!--通过带参构造初始化属性值-->
<constructor-arg name="userId" value="1"></constructor-arg>
<constructor-arg name="userName" value="ls"></constructor-arg>
</bean>
(1)获取ioc容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
(2)从容器中取出对应的bean
// 从ioc容器中取出对应的bean--->通过id获取(如果有多个bean。id值不能重复)
User user = (User) ac.getBean("u1");
// 从ioc容器中取出对应的bean--->通过类型获取(如果有多个相同类型的bean,会报错)
User user = (User) ac.getBean(User.class);
2.依赖注入
DI (Dependency Injection):依赖注入是指在 Spring IOC 容器创建对象的过程中,将所依赖的对象通过配置进行注入。我们可以通过依赖注入的方式来降低对象间的耦合度。本质上还是IOC的意思,依赖注入只是IOC的一种具体体现
<bean id="u1" class="com.hqyj.gyq.entity.User">
<!--通过带参构造初始化属性值-->
<constructor-arg name="userId" value="1"></constructor-arg>
<constructor-arg name="userName" value="ls"></constructor-arg>
<!--如果属性类型是自定义的bean类型,通过ref引用注入,ref的值:要注入的bean的id值-->
<property name="idCard" ref="card1"></property>
</bean>
<bean id="card1" class="com.hqyj.gyq.entity.IdCard">
<property name="cId" value="2"></property>
<property name="address" value="成都"></property>
<property name="cNum" value="53324534534546576"></property>
</bean>
其余注入方式(了解):list、map、set、array
3.自动装配
自动装配就是指 Spring 容器在不使用 <constructor-arg> 和<property> 标签的情况下,可以自动装配(autowire)相互协作的 Bean 之间的关联关系,将一个 Bean 注入其他 Bean 的 Property 中。
①基于xml文件有5中方式
no:默认值,表示不使用自动装配,Bean 依赖必须通过 ref 元素定义。
byName:根据 Property 的 name 自动装配,如果一个 Bean 的 name 和另一个 Bean 中的 Property 的 name 相同,则自动装配这个 Bean 到 Property 中。(表示按属性名称自动装配,XML 文件中 Bean 的 id 必须与类中的属性名称相同)
byType:根据 Property 的数据类型(Type)自动装配,如果一个 Bean 的数据类型兼容另一个 Bean 中 Property 的数据类型,则自动装配(XML 文件中 Bean 的 id 与类中的属性名称可以不同,但必须只有一个类型的 Bean。)
constructor:类似于 byType,根据构造方法参数的数据类型,进行 byType 模式的自动装配。(类中构造函数的参数必须在配置文件中有相同的类型)
autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
自动装配的其他属性:
scope:控制spring中bean是单例还是多例, prototype:多例 ,singleton:单例
xml配置文件
<bean id="u" class="com.hqyj.gyq.entity.User" autowire="byType" scope="singleton">
<property name="userId" value="2"></property>
<property name="userName" value="zs"></property>
<!-- <property name="idCard" ref="card"></property>-->
</bean>
<!--
IdCard
id="idCard" 与User类中的属性名要一致(private IdCard idCard;)
适用于用过名字自动装配
-->
<bean id="idCard" class="com.hqyj.gyq.entity.IdCard">
<property name="cId" value="1"></property>
<property name="address" value="成都"></property>
<property name="cNum" value="5124534534534665"></property>
</bean>
②使用注解
@Component:用来描述Spring中的Bean,仅仅表示一个组件(Bean),并且可以作用在任何层次,使用时只需要将该注解标注在相应类上即可。
@Controller:通常作用在控制层(如 Struts2 的 Action、SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service:通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Repository:用于将数据访问层(DAO层)的类标识为Spring中的Bean,其功能和@Component相同
@Service:放在service实现类上,作用就等同于在IOC容器中配置了一个bean
@Autowired:可以应用到 Bean 的属性变量、属性的 setter 方法、非 setter 方法及构造函数等,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功,如果ioc容器中没有任何bean类型和要注入的变量类型匹配则报错
@Resource:作用于@Autowired相同,区别在于@Resource可以通过Bean实例名称进行装配,也就是@Resource中的两个重要属性name和type。
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:component-scan base-package="com.hqyj.gyq.*"></context:component-scan>
</beans>
service层
package com.hqyj.gyq.service.impl;
import com.hqyj.gyq.dao.UserDao;
import com.hqyj.gyq.entity.User;
import com.hqyj.gyq.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public User queryUserById(Integer id) {
return userDao.selectUserById(10);
}
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext2.xml" })
public class SpringTest2 {
@Autowired
/**
* @Autowired:自动注入
*/
private UserService userService;
@Test
public void testSpring01(){
User user = userService.queryUserById(10);
System.out.println(user);
}
}
3.AOP
AOP:AOP(Aspect Oriented Programming)是一种面向切面的编程思想。面向切面编程是将程序抽象成各个切面,即解剖对象的内部,
将那些影响了多个类的公共行为抽取到一个可重用模块里,减少系统的重复代码,降低模块间的耦合度,增强代码的可操作性和可维护性。
AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。
横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理、增强处理。
AOP术语:
①通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
②连接点(Join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的 调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
③切点(PointCut): 可以插入增强处理的连接点。
④ 切面(Aspect): 切面是通知和切点的结合。
⑤ 引入(Introduction):允许我们向现有的类添加新的方法或者属性。
⑥织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的代理对象。
其中PointCut是用来修饰Join point(定位我们的目标方法); Aspect(切面)包含了Advice(我们要出入或者新增的代码方法)
实现原理:代理模式第一种方式(xml):
1、编写接口UserService,再编写对应的实现类UserServiceImpl:
public class UserServiceImpl implements UserService {
@Override
public void deleteUserById(Integer id) {
System.out.println("删除成功");
int num = 1/0;
}
}
2、编写切面类TxManager:
package com.hqyj.cq.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
public class TxManager {
public void start(){
System.out.println("开启事务!");
}
public void commit(){
System.out.println("提交事务!");
}
public void rollback(){
System.out.println("回滚事务!");
}
public void close(){
System.out.println("关闭事务!");
}
public void txManager(ProceedingJoinPoint joinPoint) throws Throwable {
// 执行目标方法
// joinPoint.proceed();
// 获取目标类
// Object target = joinPoint.getTarget();
// 获取目标类中执行的方法的参数
// Object[] args = joinPoint.getArgs();
// 获取执行的目标方法
// Signature signature = joinPoint.getSignature();
// System.out.println(signature);
// 开启事务
start();
try{
// 执行业务代码(目标方法被包裹的位置)
joinPoint.proceed();
// 提交事务
commit();
}catch (Exception e){
// 回滚事务
rollback();
}finally {
// 关闭
close();
}
}
}
3、在applicationContext.xml中配置:
<!--使用aop编程实现事务的管理-->
<!--配置目标类-->
<bean id="userService" class="com.hqyj.cq.service.impl.UserServiceImpl"></bean>
<!-- 配置切面类(增强类) -->
<bean id="tx" class="com.hqyj.cq.aspect.TxManager"></bean>
<!--aop配置-->
<aop:config>
<!--切入点的配置-->
<!--
id:任意取(一般都叫pointcut)
expression:
第一个*:代表的是方法的返回值
com.hqyj.cq.service.impl:包路径
第二个*:包下面的所有的类
第三个*:类下面的所有的方法
(..):方法的参数列表
-->
<aop:pointcut id="pointcut" expression="execution(* com.hqyj.cq.service.impl.*.*(..))"/>
<!--切面类注入-->
<aop:aspect id="aspect" ref="tx">
<!--配置前置通知-->
<!-- <aop:before method="start" pointcut-ref="pointcut"></aop:before>-->
<!--配置后置通知(在没有发生异常的时候执行)-->
<!-- <aop:after-returning method="commit" pointcut-ref="pointcut"></aop:after-returning>-->
<!--配置异常通知-->
<!-- <aop:after-throwing method="rollback" pointcut-ref="pointcut"></aop:after-throwing>-->
<!--配置最后通知(无论是否发生异常,最后都会执行)-->
<!-- <aop:after method="close" pointcut-ref="pointcut"></aop:after>-->
<!--配置环绕通知(自定义业务逻辑)-->
<aop:around method="txManager" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>
4、编写测试类SpringTest:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringTest {
@Autowired
private UserService userService;
@Test
public void test01(){
userService.deleteUserById(2);
}
}
第二种方式(注解):
1、编写接口UserService,再编写对应的实现类UserServiceImpl:
@Service
public class UserServiceImpl implements UserService {
@Override
public void deleteUserById(Integer id) {
System.out.println("删除成功");
int num = 1/0;
}
}
2、编写切面类TxManagerAnno:
@Aspect//声明切面类
@Component//交给spring容器管理
public class TxManagerAnno {
//随意写一个没有返回值的方法用来定义切入点,方法名可以任意,
(方法名相当于xml配置中的<aop:pointcut id="pointcut" expression="execution(* com.hqyj.cq.service.impl.*.*(..))"/>
的id值)
@Pointcut("execution(* com.hqyj.cq.service.impl.*.*(..))")
public void pointcut(){
}
//
// @Before("pointcut()")
public void start(){
System.out.println("开启事务!");
}
//
// @AfterReturning("pointcut()")
public void commit(){
System.out.println("提交事务!");
}
// @AfterThrowing("pointcut()")
public void rollback(){
System.out.println("回滚事务!");
}
// @After("pointcut()")
public void close(){
System.out.println("关闭事务!");
}
@Around("pointcut()")
public void txManager(ProceedingJoinPoint joinPoint) throws Throwable {
// 开启事务
start();
try{
// 执行业务代码(目标方法被包裹的位置)
joinPoint.proceed();
// 提交事务
commit();
}catch (Exception e){
// 回滚事务
rollback();
}finally {
// 关闭
close();
}
}
}
3、在applicationContext1.xml中配置:
<!--开启包扫描-->
<context:component-scan base-package="com.hqyj.cq.*"></context:component-scan>
<!--开启aop注解驱动-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4、编写测试类SpringTestAnno:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext1.xml"})
public class SpringTestAnno {
@Autowired
private UserService userService;
@Test
public void test01(){
userService.deleteUserById(2);
}
@Test
public void test02(){
userService.updateUserById(2);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext1.xml"})
public class SpringTestAnno {
@Autowired
private UserService userService;
@Test
public void test01(){
userService.deleteUserById(2);
}
@Test
public void test02(){
userService.updateUserById(2);
}
}