Spring
Spring
Java应用最广泛的框架 ,它的成功来源于理念,而不是技术本身。
-
IOC 控制反转
-
AOP 面向切面编程
-
DI 依赖注入
非侵入式设计: 无需继承框架提供的任何一个类,更换框架,代码基本上不需要大改
Spring优势
-
低侵入/低耦合
-
声明式事务(基于AOP)
-
方便集成其他框架
-
降低了Java的开发难度
-
提供了JavaWeb三层的每一层的解决方案
SpringBean
SpringBean是JavaBean的扩展,但是已经完全不是一回事了。
现在的JavaBean作为对象,要求每个属性提供setget方法,Spring的bean只需要为接收设置的值注入提供set方法
什么是Bean管理
-
Spring创建对象
-
Spring注入属性
Bean管理操作的方式
-
基于xml配置文件方式实现
-
基于注解方式实现
Spring的Bean生命周期
1.构造
2.注入
3.初始化
4.销毁
懒初始化(延迟初始化)
1.servlet的初始化 默认为懒初始化 Load-on-startup
2.spring的IOC容器 默认就是非懒初始化,只要spring的容器启动 所有的bean都会加载 都会初始化
IOC
控制反转 IOC容器!!!
基于xml配置文件方式实现
IOC操作Bean管理 (基于XML方式)
-
基于xml创建对象
-
基于xml注入属性
注入属性
第一种注入属性方式:Set注入
<!-- set方式注入属性-->
<!--创建对象 -->
<bean id="book" class="com.jsoft.entity.Book">
<!--set注入属性-->
<property name="name" value="张三讲刑法"></property>
<property name="author" value="张三"></property>
</bean>
第二种注入方式 使用有参构造器注入
<!--创建对象 -->
<bean id="book" class="com.jsoft.entity.Book">
<!--有参构造注入属性-->
<constructor-arg name="name" value="西游记"></constructor-arg>
<constructor-arg name="author" value="孙悟空"></constructor-arg>
</bean>
P名称空间注入(了解)
-
使用P名称空间注入 可以简化基于xml配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<!--p 名称空间声明-->
xmlns:p="http://www.springframework.org/schema/p"
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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--创建对象 p名称空间赋值-->
<bean id="book" class="com.jsoft.entity.Book" p:name="九阳神功" p:author="无名氏"> </bean>
测试类调用创建的对象
public void testPrintBook(){
//1.加载配置文件
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("application.xml");
//2.获取配置对象
Book book = context.getBean("book",Book.class);
//3.调用方法 打印
book.printBook();
}
注入null值
使用<null/>
<property name="address"><null/></property>
注入特殊符号
-
使用< ; > ;
-
把带特殊符号的内容写道CDATA中去 <![CDATA[特殊符号的具体值]]>
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
注入外部Bean
xml 部分
<!-- 1.service 和 dao对象创建 -->
<bean id="bookDao" class="com.jsoft.dao.BookDaoImpl"></bean>
<bean id="bookService" class="com.jsoft.service.BookService">
<!-- 注入userDao对象
name 类里面属性名称
ref 依赖 创建userDao对象bean的id值
-->
<property name="bookDao" ref="bookDao"></property>
</bean>
java部分
注入属性内部Bean
<!--常规定义Bean-->
<bean id="emp" class="com.jsoft.entity.Emp">
<property name="name" value="张三"></property>
<property name="gender" value="男"></property>
<!--定义内部Bean-->
<property name="dept">
<bean id="dept" class="com.jsoft.entity.Dept">
<property name="name" value="安保部"></property>
</bean>
</property>
</bean>
级联赋值
(1)第一种写法 外部定义bean 直接赋值
<bean id="emp" class="com.jsoft.entity.Emp">
<property name="name" value="张三"></property>
<property name="gender" value="男"></property
<!--级联赋值 -->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.jsoft.entity.Dept">
<property name="name" value="安保部"></property>
</bean>
(2)第二种写法 外部定义bean 在内部调用属性赋值
<bean id="emp" class="com.jsoft.entity.Emp">
<property name="name" value="张三"></property>
<property name="gender" value="男"></property>
<!--级联赋值 -->
<property name="dept" ref="dept"></property>
<!--调用dept属性name赋值 需要dept类 有get方法 -->
<property name="dept.name" value="财务部"></property>
</bean>
<bean id="dept" class="com.jsoft.entity.Dept"></bean>
Bean类型
-
普通bean 在配置文件中定义的bean类型和返回类型相同
-
工厂bean(FactoryBean) 配置文件定义的bean类型可以和返回类型不同
-
第一步 创建类 让这个类作为工厂bean 实现接口FactoryBean
-
第二步 实现接口里面的方法 在实现的方法中定义返回的bean类型
-
IOC操作Bean管理(bean作用域)
-
在spring里面 可以设置创建bean实例是单实例还是多实例
-
在spring里面 默认情况下 bean是单实例对象
-
如何设置是单实例还是多实例
-
在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
-
scope属性值
-
第一个值 默认值 singleton 表示单例模式
-
第二个值 prototype 表示是多实例对象
-
-
singleton和prototype区别
-
第一 singleton 是单实例 prototype 是多实例
-
设置scope值是singleton时候 加载spring配置文件时候就会创建单实例对象
-
设置scope值是prototype时候 不是在加载spring配置文件时候创建对象 在调用getBean方法时候创建多实例对象
-
-
<!--创建对象 -->
<bean id="book" class="com.jsoft.entity.Book" scope="prototype">
<property name="name" value="大话西游"></property>
<property name="author" value="孙悟空"></property>
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
</bean>
singleton 比较两个对象 true prototype 比较两个对象 false
IOC操作Bean管理(bean生命周期)
-
通过构造器创建bean实例(无参构造器)
-
为bean的属性设置值和对其他bean引用(调用set方法)
-
调用bean的初始化的方法(需要进行配置初始化的方法)
-
bean可以使用了(对象获取到了)
-
当容器关闭时候 调用bean的销毁的方法 (需要进行配置销毁的方法) 默认不调用 需要手动销毁bean
public class Orders {
private String name;
public void setName(String name) {
this.name = name;
System.out.println("第二步 调用set方法设置属性");
}
public Orders() {
System.out.println("第一步 执行无参构造创建bean实例");
}
public void initMethod(){
System.out.println("第三步 执行初始化的方法");
}
public void destoryMethod(){
System.out.println("第五步 执行了销毁方法");
}
<bean id="orders" class="com.jsoft.entity.Orders"
init-method="initMethod" destroy-method="destoryMethod">
<!--手动设置初始化方法和销毁方法-->
<property name="name" value="手机"></property>
</bean>
如果加入 bean的后置处理器 bean的生命周期有七步
-
通过构造器创建bean实例(无参构造器)
-
为bean的属性设置值和对其他bean引用(调用set方法)
-
把bean实例传递给bean后置处理器 postProcessBeforeInitialization
-
调用bean的初始化的方法(需要进行配置初始化的方法)
-
把bean实例传递给bean后置处理 postProcessAfterInitialization
-
bean可以使用了(对象获取到了)
-
当容器关闭时候 调用bean的销毁的方法 (需要进行配置销毁的方法) 默认不调用 需要手动销毁bean
//创建后置处理器 实现BeanPostProcessor 接口 并重写方法
public class MyBeanPost implements BeanPostProcessor {
<!-- 配置后置处理器 该配置文件里的所有bean都可以使用-->
<bean id="myBeanPost" class="com.jsoft.entity.MyBeanPost"></bean>
IOC操作Bean管理(xml自动装配 autowire)
什么是自动装配
-
根据指定装配规则,(属性名称或者属性类型),spring自动将匹配的属性值进行注入
-
bean 标签属性 autowire 配置自动注入
-
autowire 属性常用两个值:
-
byName 根据属性名注入 注入的bean的id值和类属性名称一样
-
ByType 根据属性类型注入
-
-
<!-- autowire 两种类型(根据名称 根据类型) 配置好文件后他自己回去找名字相同的类或属性-->
<bean id="emp" class="com.jsoft.entity.Emp" autowire="byType/byName">
<!-- <property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.jsoft.entity.Dept"></bean>
IOC操作Bean管理(外部属性文件)
-
直接配置数据库信息
(1) 配置Druid连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mhl
?rewriteBatchedStatements=true"></property>
<property name="username" value="root"></property>
<property name="password" value="123"></property>
</bean>测试类
public void test() throws SQLException {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("bean4.xml");
DataSource dateSource = (DataSource)context.getBean("dataSource");
Connection connection = dateSource.getConnection();
System.out.println(connection);
connection.close();
}(2) 引入Druid连接池依赖Jar包
基于注解方式实现
IOC操作Bean管理 (基于注解方式)
什么是注解?
-
注解是代码特殊标记 格式:@注解名称(属性名称=属性值,属性名称=属性值...)
-
使用注解 注解作用在类 方法 属性上面
-
使用注解的目的? 简化xml文件配置
Spring针对Bean管理中创建对象提供注解
(*下面四个注解功能都是一样的 都可以用来创建bean实例)
@Component:可以用于注册所有bean
@Controller:主要用于注册控制层的bean
@Service:主要用于注册服务层的bean
@Repository:主要用于注册dao层的bean
Bean管理注解方式(创建对象)
-
配置文件
-
开启组件扫描
<!-- 开启组件扫描-->
<content:component-scan base-package="com.jsoft"></content:component-scan>
-
创建类 在类上面添加创建对象注解
//就相当于 <bean id="" class="">
// 在注解里面value属性值可以省略不写 默认值是类名称 首字母小写
Bean管理注解方式(扫描配置)
use-default-filters 默认为trye 扫描默认路径 false 扫描自定义配置
content:include-filter 设置扫描哪些内容
content:exclude-filter 设置不扫描哪些内容
expression 扫描或不扫描类型
<content:component-scan base-package="com.jsoft" use-default-filters="false">
<content:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</content:component-scan>
<content:component-scan base-package="com.jsoft">
<content:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</content:component-scan>
Bean管理注解方式(注入属性@Autowired和Qualifier)
-
@Autowired 根据属性类型自动注入
-
@Qualifier 根据属性名称自动注入 (需要搭配@Autowired使用)
-
@Resource 根据引用类型注入 也可以根据名称注入 (它是javax包中的 不属于spring)
-
@Value 注入普通类型属性
Bean管理注解方式(完全注解开发)
-
创建配置类 代替配置文件
-
编写测试类
测试类
public class UserTest {
AOP
-
面向切面编程 主要用来解决一些系统层面上的问题 比如日志 事务 权限
-
在不改变原有逻辑的基础上 增加一些额外的功能
-
AOP是OOP(面向对象)的补充和完善
-
AOP横切技术 剖解开对象的内部 把一些和业务无关 却可以为业务共同的调用的逻辑封装起来 减少重复代码的使用
底层原理
AOP底层动态代理
-
有接口情况 使用JDK动态代理
创建一个该接口实现类的代理对象 增强类的方法
public class JDKProxy { -
没有接口情况 使用CGLIB动态代理
创建当前子类的代理对象 增强类的方法
AOP动态代理
使用JDK动态代理 使用Proxy类里面的方法 newProxyInstance 创建代理对象
该方法有三个参数:
第一个参数 类加载器
第二个参数 增强方法的所在的类 这个类实现的接口 支持多接口
第三个参数 实现这个接口InvocationHandler 创建代理对象 写增强的方法
public class JDKProxy {
AOP(术语)
通知(增强)
实际被增强的逻辑部分就称为通知(增强)
-
通知有多种类型
-
前置通知 @Before 方法执行前执行
-
后置通知 @AfterReturning 方法执行后执行
-
环绕通知 @Around 方法执行前后后都执行(优先级最高)
-
异常通知 @AfterThrowing 方法发生异常时执行
-
最终通知 @After 方法无论发生什么都执行(类似finally)
-
连接点
类里面哪些方法可以被增强,这些方法就被称为连接点
切入点
实际被增强的方法 就称为切入点
切面
把通知应用到切入点的过程就是切面 是一个动作
织入
被通知的对象 真正的业务逻辑 可以毫不知情。两者互相之间可能并不知情 专注于自己该做的事
AOP操作(准备)
Spring框架一般都是基于AspectJ实现AOP操作
什么是AspectJ?
AspectJ不是Spring组成部分 独立AOP框架 一般把AspectJ和Spring框架一起使用,进行AOP操作
基于AspectJ实现AOP操作
切入点表达式
切入点表达式作用 知道对哪个类里面的哪个方法进行增强
语法结构 execution ( [权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]) )
例: 对com.jsoft.dao.BookDao 类里面的add进行增强 execution(* com.jsoft.dao.BookDao.add(...))
对com.jsoft.dao.BookDao类里面的所有的方法进行增强 execution(* com.jsoft.dao.BookDao.*(...))
对com.jsoft.dao 包里面的所有类 所有方法进行增强 execution(*com.jsoft.dao. *. * (...))
AOP操作(基于AspectJ注解方式)
步骤:
(1)创建类 在类里面定义方法
public class User {
public void add(){
System.out.println("add...");
}
}
(2)创建增强类(编写增强逻辑)
public class UserProxy {
public void before(){
System.out.println("before...");
}
}
(3)进行通知的配置
(3.1)在Spring配置文件中 开启注解扫描
<context:component-scan base-package="com.aop"></context:component-scan>
(3.2)使用注解创建User和UserProxy对象
(3.3)在增强类上面添加注解@Aspect( 切面声明)
(3.4)在Spring配置文件中开启生成代理对象
<!--开启AspectJ生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
(4)配置不同类型的通知
//在方法名前 加@Before修饰符
公共切入点抽取
对于重复调用的切入点 抽取出来
//创建切入点方法point
增强类优先级
有多个增强类同时增强一个方法 可以设置增强类优先级
AOP操作(基于AspectJ配置文件)
操作步骤:
1.创建两个类 增强类和被增强类 创建方法
public class Animal {
public void eat(){
System.out.println("一顿八碗米。。。");
}
}
public class AnimalProxy {
public void eatPro(){
System.out.println("一顿吃十碗。。。");
}
}
2.在spring 配置文件中创建两个类对象
<bean id="animal" class="com.aop1.Animal"></bean>
<bean id="animalProxy" class="com.aop1.AnimalProxy"></bean>
3.在spring配置文件中配置切入点
<!--配置aop增强-->
<aop:config>
<!--声明切入点-->
<aop:pointcut id="p" expression="execution(* com.aop1.Animal.eat(..))"/>
<!--配置切面-->
<aop:aspect ref="animalProxy">
<!--配置作用在具体方法上-->
<aop:before method="eatPro" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
测试类
public class Test {
完全使用注解开发
1.创建配置类
2.创建增强类和被增强类并注入ioc容器中
JdbcTemplate(暂定)
Spring事务的7种传播行为
-
required 如果当前没有事务 新建一个事务 如果有 就加入这个事务
-
supports 支持当前的事务 如果没有事务 就以非事务的方法运行
-
mandatory 使用当前的事务 如果没有事务 就抛异常
-
requires_new 新建事务 如果当前存在事务 就把当前事务挂起
-
not_supported 以非事务刚发执行 如果有事务 当没事务执行
-
never 如果没有事务 正常运行 如果有事务 就抛异常
-

浙公网安备 33010602011771号