Spring5框架总结
Spring框架概述
1、Spring框架是轻量级的开源的JavaEE框架
2、Spring框架可以解决企业应用开发的复杂性
3、Spring有两个核心的部分:IOC和AOP
(1)IOC:控制反转,把创建对象的过程,交给Spring进行管理
(2)AOP:面向切面,不修改源代码的情况下,进行功能的增强
4、Spring相关的特点
(1)方便解耦,简化开发
(2)AOP编程支持
(3)方便程序测试,Unite测试
(4)方便集成各种优秀框架,整合其他框架
(5)方便进行事物的操作,降低API的开发难度
下载Spring
选取Spring版本为
官网 : http://spring.io/
官方下载地址 : https://repo.spring.io/libs-release-local/org/springframework/spring/
GitHub : https://github.com/spring-projects
选择合适的版本下载。这里下载的是5.2.6版本的
案例
打开idea,新建一个项目
创建好项目之后,开始导入spring的相关的jar包
Spring5的模块
架包
把架包导入到idea中
然后创建一个普通的类,然后类中创建普通方法
public class User {
public void add(){
System.out.println("add..........");
}
}
创建这个Spring配置文件,然后在配置文件中创建配置的对象
(1)Spring配置文件使用xml创建
用测试代码编写
输出结果
IOC容器
1.IOC底层原理
1. 什么是IOC
(1)控制反转,把对象的创建和对象之间调用的过程,交给Spring进行管理
(2)使用IOC的目的:为了耦合度降低
(3)做入门的案例,就是IOC的实现
2.IOC的底层原理
(1)xml解析、工厂模式、反射
最终的目的就是降低限度
IOC过程:
也是进一步降低耦合度
第一步 xml配置文件,配置创建的对象
第二步:有service类和dao类,创建工厂类
class UserFactory{
public static UserDao getDao(){
String classValue = class属性值;//xml解析
//通过反射来创建对象
Class clazz=Class.forName(classValue);//括号里面是路径。
return(UserDao)clazz.newInstance();
}
}
2.IOC接口(BeanFactory)
1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2.Spring提供了IOC容器的两种方式(两个接口)
(1)BeanFactory:IOC容器基本实现方式,是Spring内部的使用接口,不提供开发人员使用。加载配置文件的时候,不会创建对象,在使用的时候,才会创建对象。
(2)ApplicationContext:BeanFactory接口的子接口,提供更加强大的功能,一般由开发人员使用。加载配置文件的时候,就会在配置文件对象时创建对象。
3.ApplicationContext接口有实现类
FIleSystemXmlApplicationContext 需要写全路径
ClassPathXmlAppalachianContext就是写双人床对应的路径
3.IOC操作Bean管理(基于xml)
1、什么是Bean管理
(0)Bean管理指两个操作
(1)Spring创建对象
(2)Spring注入属性
2、Bean管理的操作有两种实现方式
(1)基于xml配置文件方式实现
(2)基于注解方式实现
IOC操作Bean管理操作
1、基于xml方式创建对象
<bean id="user" class="Spring5.User"></bean>
(1)在Spring配置文件中,使用Bean标签,标签里面添加相应的属性,就可以实现对象创建
(2)在bean标签中有很多属性,介绍常用的属性
*id属性:唯一标识
*class属性:类全路径(包类路径)
*name属性:id属性不能加特殊符号,而name可以添加特殊符号。一般使用id属性
(3)创建对象的时候,默认也是执行无参构造方法
2、基于xml方式注入属性
(1)DI:依赖注入,就是注入属性
第一种注入方式:使用set方法进行注入
创建类,定义属性和对应的set方法
在Spring配置文件中配置对象的创建,在配置属性的注入
xml配置文件
<!-- 2 set方法注入属性-->
<bean id="book" class="Spring5.Book">
<!--在bean标签 property完成属性注入
name: 类里面的属性
value:向属性中注入值
-->
<property name="bname" value="易筋经"></property>
<property name="bauthor" value="达摩"></property>
</bean>
类中的属性以及set方法
private String bname;
private String bauthor;
//创建属性对应的set方法注入
public void setBname(String bname) {
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}
public void testDemo(){
System.out.println(bname+"" +bauthor);
}
测试类中的:加载Spring配置文件
public void testBook1(){
ApplicationContext context = new ClassPathXmlApplicationContext("Spring5/bean1.xml");
Book book = context.getBean("book",Book.class);
System.out.println(book);
book.testDemo();
}
第二种注入方式:使用有参构造进行注入
创建类,定义属性,创造有参数构造方法
public class Orders {
// 属性
private String oname;
private String address;
// 有参构造
public Orders(String oname, String address) {
this.oname = oname;
this.address = address;
}
public void ordersTest(){
System.out.println(oname+address);
}
xml配置文件
<bean id="orders" class="Spring5.Orders">
<constructor-arg name="oname" value="abc"></constructor-arg>
<constructor-arg name="address" value="中国"></constructor-arg>
</bean>
测试类方法
public void testorders(){
ApplicationContext context = new ClassPathXmlApplicationContext("Spring5/bean1.xml");
Orders orders = context.getBean("orders",Orders.class);
System.out.println(orders);
orders.ordersTest();
}
p名称空间注入
使用p名称空间注入,可以简化基于xml配置方式
第一步:添加一个p名称空间在配置文件中
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
第二步:进行属性注入,在bean标签里面进行操作
<bean id="book" class="Spring5.Book" p:bname="九阳" p:bauthor="无人"> </bean>
1、IOC操作Bean管理(xml注入其他类型限制)
1、字面量
(1)null值
<bean id="book" class="Spring5.Book">
<!--在bean标签 property完成属性注入
name: 类里面的属性
value:向属性中注入值-->
<!-- –>-->
<property name="bname" value="易筋经"></property>
<property name="bauthor" value="达摩"></property>
<!-- 设置一个空值 -->
<property name="address" >
<null/>
</property>
</bean>
private String bname;
private String bauthor;
private String address;
//创建属性对应的set方法注入
public void setBname(String bname) {
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}
public void setAddress(String address) {
this.address = address;
}
public void testDemo(){
System.out.println(bname+"" +bauthor+address);
}
(2)属性值包含特殊符号
<!-- 属性值中包含特殊符号
1 把<>进行转义 <>
2 把带特殊符号内容写到CDATA中
-->
<property name="address">
<value>
<![CDATA[<<南京>>]]>
</value>
</property>
2、注入属性-外部Bean
(1)创建两个类service类和dao类
(2)在service调用dao里面的方法
(3)在Spring的配置文件中进行配置
service 代码
public class UserService {
//1 创建UserDao类型属性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add.................");
userDao.update();
/*
首先创建UserDao对象
UserDao userDao = new UserDaoImpl();
userDao.update();
*/
}
dao层代码
public class UserDaoImpl implements UserDao {
@Override
public void update() {
System.out.println("dao update.......... ");
}
}
public interface UserDao {
public void update();
}
配置文件
<!-- 1、service和dao对象创建-->
<bean id="userService" class="Spring5.service.UserService">
<!-- 注入UserDao对象
name属性值:类里面属性名称
ref属性:创建userDao对象bean标签id值
-->
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="Spring5.dao.UserDaoImpl">
</bean>
3、注入属性-内部Bean
(1)数据库一对多关系:部门和员工 一个部门有多个员工,一个员工属于一个部门 部门是一,员工是多
(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象属性进行表示
//部门类
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
}
//员工类
public class Emp {
private String ename;
private String gender;
//员工属于某一个部门
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
}
(3)在Spring配置文件中进行配置
<!-- 内部bean-->
<bean id="emp" class="Spring5.bean.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<!-- 对象类属性-->
<property name="dept">
<bean id="dept" class="Spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
4、注入属性-级联赋值
<!-- 级联赋值-->
<bean id="emp" class="Spring5.bean.Emp">
<!-- 设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<!-- 级联赋值-->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="Spring5.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
5、IOC操作Bean管理(xml注入集合属性)
1、注入数组类型属性
2、注入list集合类型属性
3、注入Map集合类型属性
(1)创建类,定义数组、list、map、set类型属性,生成对应的set方法
package Spring5Demo;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Stu {
//1 数组类型属性
private String[] courses;
public void setCourses(String[] courses) {
this.courses = courses;
}
//2 list集合类型属性
private List<String> list;
//3 map集合类型
private Map<String,String> maps;
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
//4 set集合类型属性
private Set<String> sets;
public void setSets(Set<String> sets) {
this.sets = sets;
}
}
(2)在Spring中配置文件
<!--集合类型属性注入-->
<bean id="stu" class="Spring5Demo.Stu">
<!-- 数组类型属性注入-->
<property name="courses">
<array>
<value>Java课程</value>
<value>数据库课程</value>
</array>
</property>
<!-- list集合类型属性注入-->
<property name="list">
<list>
<value>张三</value>
<value>小三</value>
</list>
</property>
<!-- map属性类型注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!-- set集合注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
4、在集合里面设置对象属性值
<!-- 注入list集合类型,值是对象-->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<!-- 创建多个course对象-->
<bean id="course1" class="Spring5Demo.Course">
<property name="cname" value="Spring5框架课程"></property>
</bean>
<bean id="course2" class="Spring5Demo.Course">
<property name="cname" value="MyBatis框架"></property>
</bean>
//课程
public class Course {
private String cname;//课程名称
public void setCname(String cname) {
this.cname = cname;
}
//学生学的多门的课程
private List<Course> courseList;
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
5、把集合注入部分提取出来
(1)在Spring配置文件中引入名称空间util
添加,修改一部分,把beans改成util
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 把list注入部分提取出来-->
</beans>
(2)使用util标签完成list集合注入提取
<!-- 把list注入部分提取出来-->
<util:list id="bookList">
<!-- <ref bean=""></ref> 这个是对象-->
<value>中华上下五千年</value>
<value>大国崛起</value>
</util:list>
<!-- 提取list集合类型注入使用-->
<bean id="book" class="Spring5Demo.Book">
<property name="list" ref="bookList"></property>
</bean>
4.IOC操作Bean管理(工厂Bean)
Spring有两种类型的Bean,一种普通的Bean,另外一种是工厂Bean。
普通bean:特点就是在配置文件bean类型就是返回类型
工厂bean:在配置文件中定义的bean类型可以和返回值类型不一样
第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步:实现接口的方法,在实现的方法里面定义返回的bean类型
1、IOC操作Bean管理(Bean作用域)
(1)在Spring里面,设置创建笨啊实例是单实例还是多实例
(2)在spring中,默认情况下,bean是单实例现象
(3)如何设置单实例还是多实例
在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
scope属性值有多个:
第一个默认值:singleton,表示单实例对象 结果是对象相同
第二个值:prototype,表示多实现对象
区别:设置scope值是singleton时候,加载spring配置文件的时候,就会创建一个单实例的对象
设置scope值是prototype时候,不是在加载spring配置文件的时候,加载对象,而是在调用getbean方法的时候,创建对象。
<bean id="book" class="Spring5Demo.Book" scope="prototype">
<property name="list" ref="bookList"></property>
</bean>
结果是不同,就是说明多实现对象
2、IOC操作Bean管理(Bean生命周期)
生命周期:从对象的创建到对象的销毁的过程为生命周期
2.1 bean的声明周期
(1)通过构造器去创建bean实例(无参构造)
(2)为bean的属性来设置值和对其他bean的引用(调用set方法)
(3)调用bean的初始化方法(需要进行配置)
(4)bean可以使用了(对象获取到了)
(5)当容器关闭的时候,调用bean的销毁的方法(需要进行配置销毁的方法)
2.2 演示bean的声明周期
public class Order {
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 调用set方法设置属性值");
}
//无参构造
public Order(){
System.out.println("第一步 执行无参构造创建Bean实例");
}
//创建执行的初始化方法
public void initMethod(){
System.out.println("第三步 执行初始化的方法");
}
//创建销毁的方法
public void destoryMethod(){
System.out.println("第五步,执行销毁的方法");
}
}
<?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="order" class="Spring5.bean.Order" init-method="initMethod" destroy-method="destoryMethod">
<property name="oname" value="手机"></property>
</bean>
</beans>
public void testBean3(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
//获取操作的对象
Order order = context.getBean("order", Order.class);
System.out.println("第四步 获取创建bean实例对象");
System.out.println(order);
//手动让bean实例销毁
((ClassPathXmlApplicationContext) context).close();
}
2.3 bean的后置处理器,bean的声明周期为七步
(1)通过构造器去创建bean实例(无参构造)
(2)为bean的属性来设置值和对其他bean的引用(调用set方法)
(3)把bean实例传递bean后置处理器的方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
(4)调用bean的初始化方法(需要进行配置)
(5)把bean实例传递bean后置处理器的方法
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
(6)bean可以使用了(对象获取到了)
(7)当容器关闭的时候,调用bean的销毁的方法(需要进行配置销毁的方法)
2.4 添加后置处理器效果
(1)创建类,实现接口
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后的方法");
return bean;
}
}
<!-- 配置后置处理器-->
<bean id="myBeanPost" class="Spring5.bean.MyBeanPost">
</bean>
5.IOC操作Bean管理(xml自动装配)
之前我们是手动装配,就是自己写配置,然后自动装配就是xml自动装配
根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入
演示自动装配
public class Emp {
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"dept=" + dept +
'}';
}
public void test(){
System.out.println(dept);
}
}
public class Dept {
}
<!-- 实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用两个值:
byName根据属性的名称注入 ,注入的值bean的id值和类属性名相同
byType根据属性的类型注入
-->
<bean id="emp" class="Spring5.autowire.Emp" autowire="byName">
<!-- <property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="Spring5.autowire.Dept">
</bean>
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
//获取操作的对象
Emp emp = context.getBean("emp", Emp.class);
System.out.println(emp);
}
使用byType的时候,如果遇到相同的属性名相同的时候,应该使用byName
6.IOC操作管理(外部属性文件)
直接配置数据库信息
配置德鲁伊连接池
引入德鲁伊连接池依赖jar包
直接配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jabc:mysql://localhost:3306/vet"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
引入外部属性文件配置数据库连接池
创建外部属性文件,properties格式文件,写数据库信息
把外部properties属性文件引入到spring配置中
引入context名称空间
在Spring配置文件中使用一个标签引入外部文件
<!-- 引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.drivers}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
6.IOC操作Bean管理(基于注解方式)
什么是注解:注解是代码的特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值、、、、、)
使用注解,注解作用在类的上面,方法上面,属性上面
使用注解的目的:简化xml配置
6.1 Spring针对Bean管理创建对象提供注解
(1)@Component:表示Spring中提供一种普通的组件,都可以创建对象
(2)@Service:通常用于Service层、业务逻辑层
(3)@Controller:通常用在web层
(4)@Repository:通常用在持久层上
上面的四个注解,功能一样,都可以用来创建Bean实例
6.2 基于注解方式实现对象创建
第一步:引入依赖
先引入aop 的依赖。
第二步:开启组件扫描
首先引入名称空间,
再开启组件扫描
<!-- 开启组件扫描
1 如果扫描多个包,多个包使用逗号隔开
2 扫描那个包的上层目录
-->
<context:component-scan base-package="基于注解.Dao,基于注解.Service,基于注解.Spring5Demo"></context:component-scan>
<context:component-scan base-package="基于注解"></context:component-scan>
</beans>
第三步:创建类,在类上面添加创建对象的注解
import org.springframework.stereotype.Service;
//在注解里面value属性值可以不写,默认值是类名称,首字母小写
//注解后面的可以不写。默认就是类名第一个字母小写
@Service(value = "userService")//<bean id="userService" class="....">
public class UserService {
public void add(){
System.out.println("Service add.......");
}
}
6.3 开启组件扫描细节
扫描的时候,只写一个包名的话,就会扫描所有的类。可以细化
<!-- 示例1
use-default-filters="false" 表示现在不使用默认filter,自己配置filter
context:include-filter,设置默认扫描那些内容
-->
<context:component-scan base-package="JiYuZhuJie" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
<!-- 示例二
下面配置扫描包含所有内容
context:exclude-filter:设置哪些内容不扫描
-->
<context:component-scan base-package="JiYuZhuJie">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
6.4 基于注解方式,实现属性注入
(1)@AutoWired:根据属性类型进行自动注入
第一步:把service 和dao 对象创建,在service和dao类上面添加创建对象的注解
第二步:在service注入dao的对象,在service类添加dao类型属性,在属性上面使用注解
import JiYuZhuJie.Dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//在注解里面value属性值可以不写,默认值是类名称,首字母小写
//注解后面的可以不写。默认就是类名第一个字母小写
@Service(value = "userService")//<bean id="userService" class="....">
public class UserService {
//定义dao类型属性
//不需要添加set方法
@Autowired
private UserDao userDao;
public void add(){
System.out.println("Service add.......");
}
}
package JiYuZhuJie.Dao;
public interface UserDao {
public void add();
}
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImp implements UserDao {
@Override
public void add() {
System.out.println("dao add//");
}
}
(2)@Qualifier:根据属性的名称进行注入
这个@Qualifier注解的使用,和上面@AutoWire一起使用
一个接口有多个实现类,我们需要使用类型的名称,按名称注入
@Service(value = "userService")//<bean id="userService" class="....">
public class UserService {
//定义dao类型属性
//不需要添加set方法
@Autowired
@Qualifier(value = "userDaoImp1")
private UserDao userDao;
public void add(){
System.out.println("Service add.......");
}
}
@Repository(value = "userDaoImp1")
public class UserDaoImp implements UserDao {
@Override
public void add() {
System.out.println("dao add//");
}
}
(3)@Resource:可以根据类型注入也可以根据名称注入
和上面相似,但是一般使用上面两个,不使用这个
(4)@Value:注入普通类型属性
@Value(value = "abc")
private String name;
可以将abc注入到name中
6.5 完全注解开发
(1)创建配置类,替代xml配置文件
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"JiYuZhuJie"})
public class SpringConfig {
}
(2)编写测试类
@Test
public void testBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService",UserService.class);
System.out.println(userService);
userService.add();
}
2.AOP
面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低, 提高程序的可重用性,同时提高了开发的效率 。
在登录页面中,我们添加功能,添加一个判断的功能,原始的就是,在修改源代码的基础上判断。在不通过修改源代码的基础上,就可以通过新写一个模块,然后直接指向判断。
2.1AOP(底层原理)
AOP底层使用动态代理
(1)有两种情况动态代理
第一种:有接口情况,使用JDK动态代理
在之前的功能上,通过代理方式在增加一些功能。有接口,就是创建接口实现类的代理对象,然后通过代理对象新增一些功能。
第二种:没有接口情况,使用CGLIB动态代理
创建子类的代理对象,增强类的方法。
AOP(JDK动态代理)
使用JDK动态代理,使用proxy类里面的代理方法创建代理对象
(1)调用newProxyInstance方法
方法有三个参数:
第一个:类的加载器
第二个:增强方法所在的类,这个类实现的接口,支持多个接口
第三个:实现这个接口InvocationHandler,创建代理对象,写增强的方法。
(2)编写JDK动态代理代码
第一步:创建接口,定义方法
public interface UserDao {
public int add(int a,int b);
public String update(String id);
}
第二步:创建接口实现类,实现方法
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id;
}
}
第三步:使用Proxy类创建接口的代理对象
package Spring5AOP;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类的代理对象
Class[] interfaces = {UserDao.class};
// Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
// }
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int add = dao.add(1,2);
System.out.println(add);
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
// 1 把创建的谁的那个代理对象,把谁传递过来
//有参数的构造传递
private Object obj;
public UserDaoProxy(Object obj){
this.obj=obj;
}
//这个方法写增强的逻辑部分
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法增强之前
System.out.println("方法之前执行"+method.getName()+"传递的参数"+ Arrays.toString(args));
// 被增强的方法执行
Object res = method.invoke(obj, args);
//方法之后
System.out.println("方法之后执行--"+obj);
return res;
}
}
AOP(术语)
1、连接点
假如一个类有四个方法,分别为增删改查,然后类里面的哪些方法可以增强,这些方法成为连接点
2、切入点
假如一个类有四个方法,分别为增删改查,实际被真正增强的方法,成为切入点
3、通知(增强)
(1)实际增强的逻辑部分称为通知(增强)
(2)通知有多种类型
*前置通知:增强一个方法,就在这个方法之前执行
*后置通知:增强一个方法,就在这个方法之后执行
*环绕通知:增强一个方法,就在这个方法前后执行
*异常通知:增强一个方法,当这个方法出现异常,会执行
*最终通知:相当于:finally
4、切面
是一个动作:把通知应用到切入点过程
2.2 AOP操作(准备)
1、Spring框架一般基于AspectJ实现AOP操作
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
2、基于AspectJ实现AOP操作
(1)基于xml配置实现
(2)基于注解方式实现(使用)
3、在项目工程里面,使用AOP相关依赖
4、切入点表达式
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构
execution([权限修饰符][返回类型][类全路径][方法名称])([参数列表])
举例:对这个类进行增强里面的add方法增强
execution(*Spring5Aop.add(....))
举例:对这个类进行增强里面的所有方法增强
execution(*Spring5Aop.*(....))
举例:对包里面的所有类所有方法增强
execution(*Spring5Aop.*.*(....))
AOP操作(AspectJ注解)
1、创建一个类,在类里面定义方法(被增强类)
package AOPamo;
public class User {
public void add(){
System.out.println("add");
}
}
2、增强类(编写增强的逻辑)
(1)在增强类里面,创建方法,让不同方法代表不同通知类型
package AOPamo;
//增强类
public class UserProxy {
//前置通知
public void before(){
System.out.println("before.......");
}
}
3、进行通知的配置
(1)在Spring配置文件中,开启注解扫描
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启注册扫描-->
<context:component-scan base-package="AOPamo"></context:component-scan>
(2)使用注解创建User和UserProxy对象
注解@Compent添加在类的上面
(3)在增强类上面添加注解@Aspect
package AOPamo;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
//增强类
@Component
@Aspect //生成代理对象
public class UserProxy {
//前置通知
public void before(){
System.out.println("before.......");
}
}
(4)在Spring配置文件中,开启生成代理对象
<!-- 开启Aspect生成代理对象 就是检查看是否有Aspect注解,如果有,就是把这个对象生成一个代理对象-->
<aop:aspectj-autoproxy>
</aop:aspectj-autoproxy>
(5)配置不同类型的通知
在我们增强类的里面,作为通知方法上面添加通知类型注解,使用切入点表达
//增强类
@Component
@Aspect //生成代理对象
public class UserProxy {
//前置通知
//@Before注解表示作为前置通知
@Before(value = "execution(* AOPamo.User.add(..))")
public void before(){
System.out.println("before.......");
}
}
@Test
public void testAopAno(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean11.xml");
User user = context.getBean("user", User.class);
user.add();
}
不同通知不同的方法
package AOPamo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增强类
@Component
@Aspect //生成代理对象
public class UserProxy {
//前置通知
//@Before注解表示作为前置通知
@Before(value = "execution(* AOPamo.User.add(..))")
public void before(){
System.out.println("before.......");
}
@After(value = "execution(* AOPamo.User.add(..))")
//方法执行之后执行,不管有没有异常都执行,最终通知
public void after(){
System.out.println("after..........");
}
@AfterReturning(value = "execution(* AOPamo.User.add(..))")
//在返回值之后执行,后置通知,返回通知
public void afterReturn(){
System.out.println("AfterReturning......");
}
@AfterThrowing(value = "execution(* AOPamo.User.add(..))")
//异常通知,有异常才会执行
public void afterThrow(){
System.out.println("AfterThrowing......");
}
@Around(value = "execution(* AOPamo.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕之前......");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后。。。。。");
}
}
相同的切入点抽取
//相同的切入点进行抽取
@Pointcut(value = "execution(* AOPamo.User.add(..))")
public void poinDemo(){
}
//前置通知
//@Before注解表示作为前置通知
@Before(value = "poinDemo()")
public void before(){
System.out.println("before.......");
}
就相当于一个公共类,然后可以随便调用。
有多个增强类对同一个方法进行增强,设置增强类的优先级
(1)在增强类的上面添加一个注解@Order(数字类型值),数字类型值越小,优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy {
//相同的切入点进行抽取
@Pointcut(value = "execution(* AOPamo.User.add(..))")
public void poinDemo(){
}
//前置通知
//@Before注解表示作为前置通知
@Before(value = "poinDemo()")
public void before(){
System.out.println("Person before.......");
}
}
@Component
@Aspect //生成代理对象
@Order(2)
public class UserProxy {
//相同的切入点进行抽取
@Pointcut(value = "execution(* AOPamo.User.add(..))")
public void poinDemo(){
}
我们经常使用注解方式,不经常使用配置文件方式。
3.JdbcTemplate
1、什么是JdbcTemplate
(1)Spring框架对JDBC进行封装,使用JDBCTemplate方便实现对数据库操作
2、准备工作
(1)引入相关的jar包
(2)在Spring配置文件中,配置数据库的连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://user_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
(3)配置JDBCTemplate对象,注入DataSource
<!-- 创建JDBCTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
(4)创建service,创建dao类,在dao类注入JDBCTemplate对象。
配置文件
<!--组件扫描-->
<context:component-scan base-package="Spring5Jdbc"></context:component-scan>
<!-- 数据库连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://user_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
<!-- 创建JDBCTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
JDBCTemplate操作数据库(添加)
1、对应数据库创建实体类
Book实体类
package Spring5Jdbc.entiy;
public class Book {
private String userid;
private String username;
private String ustatus;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUstatus() {
return ustatus;
}
public void setUstatus(String ustatus) {
this.ustatus = ustatus;
}
}
2、编写service和dao
(1)在dao进行数据库添加操作
(2)调用jdbcTemplate对象里面update方法实现添加操作
*有两个参数
*第一个参数:sql语句
*第二个参数:可变参数,设置sql语句值
package Spring5Jdbc.dao1;
import Spring5Jdbc.entiy.Book;
public interface BookDao {
//添加的方法
void add(Book book);
//修改
void updateBook(Book book);
// 删除
void delete(String id);
}
package Spring5Jdbc.Service1;
import Spring5Jdbc.dao1.BookDao;
import Spring5Jdbc.entiy.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookService {
// 注入dao
@Autowired
private BookDao bookDao;
//添加的方法
public void addBook(Book book){
bookDao.add(book);
}
//修改
public void update(Book book){
bookDao.updateBook(book);
}
//删除
public void deleteBook(String id){
bookDao.delete(id);
}
}
package Spring5Jdbc.dao1;
import Spring5Jdbc.entiy.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao {
// 注入JDBCTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//添加的方法
@Override
public void add(Book book) {
//创建sql语句
String sql = "insert into t_book values(?,?,?)";
//调用方法实现
Object[] args = {book.getUserid(), book.getUsername(), book.getUstatus()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
@Override
public void updateBook(Book book) {
String sql = "update t_book set username=?,ustatus=? where user_id=?";
Object[] args = {book.getUsername(), book.getUstatus(),book.getUserid()};
int update = jdbcTemplate.update(sql, args);
System.out.println(update);
}
@Override
public void delete(String id) {
String sql = "delete from t_book where user_id=?";
int update = jdbcTemplate.update(sql, id);
System.out.println(update);
}
}
测试类
public void testBook(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean12.xml");
//获取操作的对象
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book();
// book.setUserid("2");
// book.setUsername("java");
// book.setUstatus("a");
// bookService.addBook(book);
//修改
book.setUserid("2");
book.setUsername("mysql");
book.setUstatus("lll");
bookService.update(book);
//删除
bookService.deleteBook("1");
}
JdbcTemplate操作查询数据库(查询返回某个值)
1、查询表里面有多少条记录,返回的是某个值
2、使用JdbcTemplate实现查询返回某个值的代码
有两个参数:
第一个:sql语句
第二个:返回类型的Class
//查询表中记录数
@Override
public int selectCount() {
String sql = "select count(*) from t_book";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
return count;
}
//查询表记录数
public int findCount(){
return bookDao.selectCount();
}
//查询返回某个值
int count = bookService.findCount();
System.out.println(count);
JdbcTemplate操作查询数据库(查询返回对象)
1、场景:查询图书详情
2、用JdbcTemplate实现查询返回对象
有三个参数:
第一个:sql语句
第二个:RowMapper,是接口。返回不同类型数据,使用这个接口里面实现类完成数据封装
第三个:sql语句中的问号语句值
//查询返回对象
public Book findOne(String id){
return bookDao.findBookInfo(id);
}
//查询返回对象
@Override
public Book findBookInfo(String id) {
String sql = "select * from t_book where user_id=?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
return book;
}
//查询返回对象
Book one = bookService.findOne("2");
System.out.println(one);
}
JdbcTemplate操作查询数据库(查询返回集合)
返回集合和上面差不多
1、场景:查询图书列表分页‘’
2、调用JdbcTemplate方法实现查询返回集合
有三个参数:
第一个:sql语句
第二个:RowMapper,是接口。返回不同类型数据,使用这个接口里面实现类完成数据封装
第三个:sql语句中的问号语句值
//返回查询集合
@Override
public List<Book> findAllBook() {
String sql = "select * from t_book";
List<Book> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
return query;
}
//查询返回集合
public List<Book> findAll(){
return bookDao.findAllBook();
}
//查询返回集合
List<Book> all = bookService.findAll();
System.out.println(all);
JdbcTemplate操作数据库(批量添加操作)
1、批量操作:操作表里面的多条记录
2、JdbcTemplate实现批量添加功能
有两个参数:
第一个:sql语句
第二个:List集合,添加的多条记录数据
//批量添加
public void batchAdd(List<Object[]> batchArgs){
bookDao.batchAddBook(batchArgs);
}
@Override
public void batchAddBook(List<Object[]> batchArgs) {
String sql = "insert into t_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
//批量添加
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1={"3","java","a"};
Object[] o2={"4","c++","c"};
Object[] o3={"5","jap","q"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
//调用批量添加
bookService.batchAdd(batchArgs);
JdbcTemplate操作数据库(批量修改操作)
//批量修改
public void batchUpdate(List<Object[]> batchArgs){
bookDao.batchUpdate(batchArgs);
}
//批量修改操作
@Override
public void batchUpdate(List<Object[]> batchArgs) {
String sql= "update t_book set username=?,ustatus=? where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
//批量修改操作
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1={"java1","a","3"};
Object[] o2={"c++2","c","4"};
Object[] o3={"jsp","q","5"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
bookService.batchUpdate(batchArgs);
批量删除
//批量删除
public void batchDelete(List<Object[]> batchArgs){
bookDao.batchDelete(batchArgs);
}
//批量删除
@Override
public void batchDelete(List<Object[]> batchArgs) {
String sql = "delete from t_book where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(ints);
}
//批量删除
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1={"3"};
Object[] o2={"4"};
batchArgs.add(o1);
batchArgs.add(o2);
bookService.batchDelete(batchArgs);
}
4.事务操作
1、什么是事务
(1)事务是数据库操作的最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有都操作失败。
(2)典型场景:银行转账
*Lucy转账100给Mary
*Lucy少100,Mary多100.如果断网,就是Lucy不会少,Mary不会多
2、事务特性(ACID)
(1)原子性:指的是不可分割,双方都要成功
(2)一致性:操作之前,操作之后。总量不变
(3)隔离性:在多事务操作,之间不会产生影响
(4)持久性:最终提交之后,表中数据发生变化
事务操作(搭建事务操作环境)
1、创建数据库的表,添加记录
2、创建Service,搭建dao,完成对象创建和注入
(1)service注入dao,在dao里面注入JdbcTemplate,在JdbcTemplate注入DataSource
package Spring5Tx.service;
import Spring5Tx.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
//注入dao
@Autowired
private UserDao userDao;
}
package Spring5Tx.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao {
//注入JDBC
@Autowired
private JdbcTemplate jdbcTemplate;
}
3、在dao创建两个方法:多钱的方法和少钱的方法,在service创建方法(转账的方法)
@Repository
public class UserDaoImpl implements UserDao {
//注入JDBC
@Autowired
private JdbcTemplate jdbcTemplate;
//多钱的方法
@Override
public void addMoney() {
String sql="update t_account set money=money+? where username=?";
jdbcTemplate.update(sql,100,"mary");
}
//少钱的方法 //Lucy转账100给Mary
@Override
public void reduceMoney() {
String sql="update t_account set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
@Service
public class UserService {
//注入dao
@Autowired
private UserDao userDao;
//转账的操作
public void accountMoney(){
//Lucy少100
userDao.reduceMoney();
//mary多100
userDao.addMoney();
}
}
@Test
public void TestAccount(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean12.xml");
Spring5Tx.service.UserService userService = context.getBean("userService", Spring5Tx.service.UserService.class);
userService.accountMoney();
}
3、上面代码,如果正常执行没有任何问题。但是如果上面代码在执行过程中,出现异常,有问题
(1)上面问题可以使用事务进行解决
事务操作(Spring事务管理介绍)
1、事务一般添加到JavaEE三层结构里面Service层(业务逻辑层)
2、在Spring进行事务管理操作
(1)有两种方式:编程式事务管理和声明式事务管理(使用)
3、声明式事务管理
(1)基于注解方式(使用)
(2)基于xml配置文件方式
4、在Spring里面进行声明式事务管理,底层使用AOP原理
5、Spring事务管理API
(1)提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
事务操作(注解声明式事务管理)
1、在Spring配置文件中,配置事务管理器
<!-- 创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
2、在Spring配置文件,开启事务注解
(1)在Spring配置文件中引入名称空间
<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
(2)开启事务的注解
<!-- 开始事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
3、在service类上面(获取service类里面方法上面)添加事务注解
(1)@Transactional,这个注解添加到类上面,也可以添加到方法上面
(2)如果把这个注解添加到类上面,这个类里面所有的方法都有事务
(3)如果添加到方法上面,那就是只有这个方法有事务管理
事务操作(声明式事务管理参数配置)
1、在service类上面添加@Transactional注解,在这个注解里面可以配置事务相关参数
2、propagation:事务传播行为
(1)多事务方法之间进行调用,这个过程中事物是如何进行管理的。就是对数据库数据进行变化的操作
Spring框架事物有七种行为
REQUIRED:如果add方法本身有事务,调用update方法之后,update使用当前add方法里面事务
如果add方法本身没有事务,调用update方法之后,创建新的事务
REQUIREO_NEW:使用add方法调用update方法,如果add无论是否有事务,都创建新的事务
3、isolation:事务隔离级别
(1)事务有特性称为隔离性,多事物操作之间不会产生影响。不考虑隔离性产生很多问题。
(2)有三个读问题:脏读、不可重复读、虚(幻)读
(3)脏读:在多个事务之间,一个事务未提交的事务读取到了另一个未提交事务的数据
(4)不可重复读:一个未提交的事务读取到另一提交事务修改数据
(5)幻读:一个未提交事务读取到另一提交事务添加数据
(6)通过设置事务隔离级别,解决读问题
默认REPEATABLE_READ
4、timeout:超时时间
(1)事务需要在一定的时间内进行提交,如果不提交进行回滚
(2)默认值是-1,可以设置时间,是以秒为单位。
5、readOnly:是否只读
(1)读:查询操作,写:添加修改删除操作
(2)readOnly默认值是false,表示可以查询,可以添加修改删除操作
(3)可以设置成true,设置true之后,只能查询
6、rollbackFor:回滚
(1)设置出现哪些异常进行事务回滚
7、noRollbackFor:不回滚
(1)设置出现哪些异常不进行事务的回滚
5.Spring5新功能
1、整个Spring5框架的代码基于Java8,运行时兼容JDK9,许多不建议使用的类和方法在代码库中删除
Spring5框架自带了通用的日志封装
(1)Spring5已经移除Log4jConfigListener,官方建议使用Log4j2
(2)Spring5框架整合Log4j2
第一步引入相关架包
第二步 创建log4j2.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序:OFF > FATAL > ERROR > WARN > INFO >DEBUG > TRACE > ALL-->
<!-- Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace是,可以看到log4j2内部各种详细输出-->
<configuration status="INFO">
<!-- 先定义所有的appenders-->
<appenders>
<!-- 输出日志到控制台-->
<console name="Console" target="SYSTEM_OUT">
<!-- 控制日志的输出格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</console>
</appenders>
<!-- 然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<!-- root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
<loggers>
<!-- <Logger name="sel4jTest" level="trace">-->
<!-- <AppenderRef ref="Console"/>-->
<!-- </Logger>-->
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration
测试:
Spring5框架核心容器部分支持@Nullable注解
(1)@Nullable注解可以使用在方法上面、属性上面、参数上面,表示方法的返回值可以为空,属性值可以为空,参数值可以为空。
(2)注解用在方法上面,方法返回值可以为空
@Nullable
String getId();
(3)注解使用在方法参数里面,方法参数可以为空
(4)注解使用在属性上面,属性值可以为空
@Nullable
private String Bookname;
Spring5核心容器支持函数式风格GenericApplicationContext
//函数式风格创建对象,交给Spring进行管理
@Test
public void TestGenericApplicationContext(){
//1、创建GenericApplicationContext对象
GenericApplicationContext context = new GenericApplicationContext();
//2、调用context的方法对象注册
context.refresh();
context.registerBean(User.class,()->new User());
//3、获取在Spring注册的对象
User user = (User) context.getBean("Spring5Tx.User");
System.out.println(user);
}
}
Spring5整合JUnit5
(1)整合Junit4
第一步 引入Spring相关针对测试依赖
第二步 创建测试类,使用注解方式完成
package Spring5Tx.entity;
import Spring5Tx.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)//单元测试框架
@ContextConfiguration("classpath:bean12.xml")//加载配置文件
public class JTest4 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
(2)Spring5整合JUnit5
第一步 引入Junit5的jar包
第二步 创建测试类,使用注解完成
package Spring5Tx.entity;
import Spring5Tx.service.UserService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean12.xml")
public class JTest5 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
复合注解:代替上面两个注解
@SpringJUnitConfig(locations = "classpath:bean12.xml")
支持@Nullable注解
(1)@Nullable注解可以使用在方法上面、属性上面、参数上面,表示方法的返回值可以为空,属性值可以为空,参数值可以为空。
(2)注解用在方法上面,方法返回值可以为空
@Nullable
String getId();
(3)注解使用在方法参数里面,方法参数可以为空
(4)注解使用在属性上面,属性值可以为空
@Nullable
private String Bookname;
Spring5核心容器支持函数式风格GenericApplicationContext
//函数式风格创建对象,交给Spring进行管理
@Test
public void TestGenericApplicationContext(){
//1、创建GenericApplicationContext对象
GenericApplicationContext context = new GenericApplicationContext();
//2、调用context的方法对象注册
context.refresh();
context.registerBean(User.class,()->new User());
//3、获取在Spring注册的对象
User user = (User) context.getBean("Spring5Tx.User");
System.out.println(user);
}
}
Spring5整合JUnit5
(1)整合Junit4
第一步 引入Spring相关针对测试依赖
[外链图片转存中…(img-fYiVusyR-1627371841485)]
第二步 创建测试类,使用注解方式完成
package Spring5Tx.entity;
import Spring5Tx.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)//单元测试框架
@ContextConfiguration("classpath:bean12.xml")//加载配置文件
public class JTest4 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
[外链图片转存中…(img-X2kyDU16-1627371841485)]
(2)Spring5整合JUnit5
第一步 引入Junit5的jar包
[外链图片转存中…(img-UxQcZ7aR-1627371841486)]
第二步 创建测试类,使用注解完成
package Spring5Tx.entity;
import Spring5Tx.service.UserService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean12.xml")
public class JTest5 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
复合注解:代替上面两个注解
@SpringJUnitConfig(locations = "classpath:bean12.xml")
以上就是我所总结关于Spring5框架。有需要的朋友请点个赞。总结不易。
有需要各种架包的,请在下面评论,无偿分享的哦