1.spring创建对象
我们之前的创建对象是通过new一个类来来进行创建对象。
在spring中提供了另一种基于xml的方式进行创建对象。
1.1 ioc的概念和原理
- 控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
- 使用 IOC 目的:为了耦合度降低
- xml 解析、工厂模式、反射
1.2BeanFactory 接口
1.3 IOC 操作 Bean 管理(概念)
1.4 IOC 操作 Bean 管理(基于 xml 方式)
- 案例演示
创建一个实体类
基于xml配置对象的创建(少了</bean>结尾)
创建一个xx.xml文件路径一定要在src的最外层的路径下
- 测试
采用juit4进行测试,我也用到了之前讲到的ApplicationContext创建一个对象
1.5 基于 xml 方式注入属性
(1)DI:依赖注入,就是注入属性
创建类,定义属性和对应的 set 方法
修改代码 添加get和set方法并且加入一个属性
修改xml文件 (少了</bean>结尾)
测试
1.6 有参构造方法进行xml注入
创建一个实体类
测试结果
注入 空值和其他值
1.7 外部bean注入
创建2个实体类
创建另外一个实体类
正常来说我们要在这个实体类中引用Userdao的方法要在类里面new一个对象
现在基于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">
<!--1 service和dao对象创建-->
<bean id="userService" class="com.dfp.spring5.service.UserService">
<!--注入userDao对象
name属性:类里面属性名称
ref属性:创建userDao对象bean标签id值
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.dfp.spring5.dao.UserDaoImpl"></bean>
</beans>
测试
1.8 内部bean注入
准备2个实体类员工和部门,在员工里面注入部门
在emp的bean注入属性 dept 在这个属性下嵌套一个bean实例
测试
@Test
public void testBean2() {
//1 加载spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("bean3.xml");
//2 获取配置创建的对象
Emp emp = context.getBean("emp", Emp.class);
emp.add();
}
另外的写法
外部bean,我们可以仿照上面的方法
1.9 特殊类型的注入
创建2个类
在stu注入course的对象list属性
xml配置
<bean id="stu" class="com.dfp.spring5.bean.Stu">
<!-- 数组属性-->
<property name="courses">
<array>
<value>java</value>
<value>c++</value>
</array>
</property>
<!-- list属性-->
<property name="list">
<list>
<value>天龙八部</value>
<value>大器晚成</value>
<value>孙悟空</value>
</list>
</property>
<!-- map属性-->
<property name="maps">
<map>
<entry key="课程" value="java"/>
<entry key="时间" value="周三"/>
</map>
</property>
<property name="sets">
<set>
<value>redis</value>
<value>mysql</value>
<value>mongodb</value>
<value>oss</value>
</set>
</property>
<property name="courseList">
<list>
<!-- 外部链入-->
<ref bean="c1"></ref>
<ref bean="c2"></ref>
</list>
</property>
</bean>
<!-- 定义好对象-->
<bean id="c1" class="com.dfp.spring5.bean.Course">
<property name="cname" value="好好学习"/>
</bean>
<bean id="c2" class="com.dfp.spring5.bean.Course">
<property name="cname" value="天天向上"/>
</bean>
列表外部注入的方式
新建一个类
通过外部声明列表用ref注入到book的列表,前提我们需要声明util
2.(FactoryBean)
我们发现我们在xml文件声明的实例是mybena但是我们最终创建的是course对象
2.1 单实例还是多实例
打印2个 book对象我们发现地址是一样的说明他们其实是同一个对象
修改一下配置文件
2.2 bean的生命周期
bean 的后置处理器
实现BeanPostProcessor
修改配置文件
测试
不同于上面的我们会执行后置文件的方法
2.3 自动装配
测试结果
、
2.4 上述案例演示代码
链接:https://pan.baidu.com/s/13KOkjH1oLQwTnxN2jkKK_A?pwd=77vv
提取码:77vv
3.IOC 操作 Bean 管理(基于注解方式)
- 引入依赖
- 开启组件扫描
之前我们是在配置文件中 配置一个一个bean实例现在我们开启扫描就不需要我们自己配置实例
- 添加注解
测试
3.1 组件扫描的细节配置
配置扫描那些包,或者不扫描那些包
3.2 基于注解方式实现属性注入
添加2个类
在impl类上添加@Repository注解让userDaoimpl可以被包扫描装配成bean
使用相同的测试
对比差距
因为我们在UserDaoImpl中添加了注解这个类的默认bean名称是 userDaoImpl所以在使用Qualifier注解名称不一致是会报错的
3.3完全注解开发
首先我们需要删除或者注解掉我们的xml配置文件
新建config包新建这个配置类
ComponentScan注解相当于我们xml配置文件里面的 组件扫描
重写测试方法
@Test
public void testService2() {
//加载配置类
ApplicationContext context
= new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService",
UserService.class);
System.out.println(userService);
userService.test();
}
3.4代码演示
链接:https://pan.baidu.com/s/1-EBC1fjciVC3IthBlG6ABA?pwd=vskl
提取码:vskl
4. AOP(概念)
4.1、什么是 AOP
4.2 AOP(底层原理)
创建接口实现类代理对象,增强类的方法
代码演示
创建2个类
创建代理对象
测试
这样就可以在不修改远代码的情况下改变代码的逻辑以及添加一些功能
4.2AOP(术语)
- 连接点
类中可以被增强的方式这些方法称之为连接点
- 切入点
实际真正被增强的方法称为切入点
- 通知(增强)
实际增强的逻辑部分称之为通知
- 切面
把通知应用到切入点的过程
4.3 步骤
4、切入点表达式
切入点表达式的作用:知道对那个类里面的方法进行增强
语法结构:
execution([权限修饰符][返回类型][类的全路径][方法名称]([参数列表]))
举例1:对 com.dfp.dao.BookDao 类里面的 add 进行增强
execution(*com.dfp.dao.BookDAo.add(..))
execution(*com.dfp.dao.BookDao.*(..))
4.4 基于注解的代码演示
创建3个类在增强类上添加@Aspect注解
如果对于不同的增强类实现对同一个方法进行增强,这个时候我们会如何考虑增强的方法的优先级问题呢
- order注解的数字越小优先级越高
对于作用在同一个切入点的方法我们可以吧切入点抽取出来做一个公共部分,让其他切入的方法调用这个公共的方法
-
@Pointcut(value = "execution(* com.dfp.spring5.aop.User.add(..))")
测试方法
@Test
public void testaop(){
ApplicationContext context = new ClassPathXmlApplicationContext("aopbean.xml");
User user = context.getBean("user", User.class);
user.add();
}
配置xml文件 因为我们没有使用全注解开发所以我们要在xml中配置一下基本的扫描去装配bean实例并且配置代理对象。
测试结果
4.5 基于全xml配置代理对象
创建另外2个对象
我们把before作为 buy的前置方法根据这个逻辑去配置xml文件
首先我们也是要去创建2个bean实例
切入点可以配置多个根据id唯一标识
配置切入点根据你要的切入类型和和切入点位置。
如上所示
5. 整合jdbc操作数据库
5.1 准备工作
目录结构
引入jar包
配置jdbc连接池
配置xml文件
准备数据库
5.2创建和数据对应的实体类
public class Order {
private Integer orderId;
private String orderName;
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
}
5.3 创建dao层操作数据库
对应最终的数据库增删改查都在daoImpl层进行操作
我们在service层进行数据传递或者处理最后在dao层进行数据库操作,我们用测试类来进行测试
我们主要演示核心的代码 最终上传案例代码
5.4代码演示
我们jdbcTemplate一些方法传参会传递RowMapper我们一般创建他的实现类BeanpropertyRowMapper来实现
public class jdbcTest {
@Test
public void testJdbcTemplate() {
ApplicationContext context =
new ClassPathXmlApplicationContext("jdbc.xml");
OrderService orderService = context.getBean("orderService",
OrderService.class);
Order order = new Order();
order.setOrderId(99);
order.setOrderName("Jdbc测试添加");
orderService.add(order);
}
//代码重用
public OrderService creatorderService(){
ApplicationContext context =
new ClassPathXmlApplicationContext("jdbc.xml");
OrderService orderService = context.getBean("orderService",
OrderService.class);
return orderService;
}
// 数据修改 orderId=99的数据
@Test
public void updataJdbc(){
OrderService orderService = this.creatorderService();
Order order=new Order();
order.setOrderId(99);
order.setOrderName("Jdbc测试添加+更新");
orderService.updatabyId(order);
}
//根据id删除数据
@Test
public void delDateJdbc(){
OrderService orderService = this.creatorderService();
orderService.del(2);
}
查询表记录数
@Test
public void selectCount(){
OrderService orderService = this.creatorderService();
Integer count=orderService.selectCount();
System.out.println(count);
}
//查询返回对象
@Test
public void selectOrder(){
OrderService orderService = this.creatorderService();
Order order=orderService.selectOrderById(1);
System.out.println(order.getOrderName());
}
// 查询返回集合
@Test
public void selectOrderAll(){
OrderService orderService = this.creatorderService();
List<Order> list=orderService.selectOrderAll();
for (Order item:list) {
System.out.println(item.getOrderName());
}
}
// 批量添加操作
@Test
public void moreAdd(){
OrderService orderService = this.creatorderService();
List<Object[]> orderList=new ArrayList<>();
Object[] o1 = {"77","java"};
Object[] o2 = {"88","c++"};
Object[] o3 = {"99","MySQL"};
orderList.add(o1);
orderList.add(o2);
orderList.add(o3);
orderService.moreAdd(orderList);
}
//评论修改数据
@Test
public void moreUpdate(){
OrderService orderService = this.creatorderService();
List<Object[]> orderList = new ArrayList<>();
Object[] o1 = {"99update",99};
Object[] o2 = {"88update",88};
Object[] o3 = {"77update",77};
orderList.add(o1);
orderList.add(o2);
orderList.add(o3);
orderService.moreUpdate(orderList);
}
//批量删除
@Test
public void moreDel(){
OrderService orderService = this.creatorderService();
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {99};
Object[] o2 = {88};
batchArgs.add(o1);
batchArgs.add(o2);
orderService.batchDelete(batchArgs);}
}
orderDaoImpl类代码
@Repository
public class OrderDaoImpl implements OrderDao {
//注入 JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//添加
@Override
public void add(Order order1) {
String sql="insert into t_order values(?,?)";
Object [] list={order1.getOrderId(),order1.getOrderName()};
int update = jdbcTemplate.update(sql,list);
System.out.println(update);
}
//修改数据
@Override
public void updatabyId(Order order1) {
String sql="update t_order set order_name=?where order_id=? ";
/**
* 这个参数列表的集合顺序要和sql注入值的顺序一致
*/
Object [] list={order1.getOrderName(),order1.getOrderId()};
/**
* 1.sql语句
* 2.传入list
*/
jdbcTemplate.update(sql,list);
}
//根据id删除数据
@Override
public void del(int id) {
String sql="delete from t_order where order_id=?";
/**
* 1.sql语句
* 2.id
*/
jdbcTemplate.update(sql,id);
}
查询表记录数
@Override
public Integer selectCount() {
String sql="select count(*) from t_order";
/**
* 1.sql语句
* 2.返回值类型
*/
return jdbcTemplate.queryForObject(sql,Integer.class);
}
//查询返回对象
@Override
public Order selectOrderById(int id) {
String sql="select * from t_order where order_id=?";
/**
* 1.sql语句
* 2.构造返回对象
* 3.传入id
*/
Order order = jdbcTemplate.queryForObject(sql,
new BeanPropertyRowMapper<>(Order.class), id);
return order;
}
// 查询返回集合
@Override
public List<Order> selectOrderAll() {
String sql="select * from t_order";
List<Order> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Order.class));
return query;
}
// 批量添加操作
@Override
public void moreAdd(List<Object[]> orderList) {
String sql="insert into t_order values(?,?)";
jdbcTemplate.batchUpdate(sql,orderList);
}
//批量更新数据
@Override
public void moreUpdate(List<Object[]> orderList) {
String sql="update t_order set order_name=? where order_id=?";
/**
* 注意orderList值的顺序要和sql语句出现的顺序一致
* 一个orderList的值先name再id
*/
jdbcTemplate.batchUpdate(sql,orderList);
}
//批量删除
@Override
public void batchDelete(List<Object[]> batchArgs) {
String sql="delete from t_order where order_id=?";
jdbcTemplate.batchUpdate(sql,batchArgs);
}
}
service层代码
Service
public class OrderService {
@Autowired
private OrderDao orderDao;
//添加方法
public void add(Order order) {
orderDao.add(order);
}
public void updatabyId(Order i) {
orderDao.updatabyId(i);
}
//根据id删除数据
public void del(int i) {
orderDao.del(i);
}
查询表记录数
public Integer selectCount() {
return orderDao.selectCount();
}
//查询返回对象
public Order selectOrderById(int i) {
return orderDao.selectOrderById(i);
}
// 查询返回集合
public List<Order> selectOrderAll() {
return orderDao.selectOrderAll();
}
// 批量添加操作
public void moreAdd(List<Object[]> orderList) {
orderDao.moreAdd(orderList);
}
//批量更新数据
public void moreUpdate(List<Object[]> orderList) {
orderDao.moreUpdate(orderList);
}
//批量删除
public void batchDelete(List<Object[]> batchArgs) {
orderDao.batchDelete(batchArgs);
}
}
6.事务操作(事务概念)
6.1、什么事务
6.2、事务四个特性(ACID)
6.3 场景演示
新建一下类
user用户类
public class User {
private Integer Id;
private String name;
private Float money;
public Integer getId() {
return Id;
}
public void setId(Integer id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getMoney() {
return money;
}
public void setMoney(Float money) {
this.money = money;
}
}
userDao类
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 模拟1001账户给1002账户转账
*/
//1001账户 -100
public void redMoney(){
String sql="update spring5_user set money=money-? where id=?";
jdbcTemplate.update(sql,100,1001);
}
//1002账户 +100
public void addMoney(){
String sql="update spring5_user set money=money+? where id=?";
jdbcTemplate.update(sql,100,1002);
}
}
@Transactional //添加事物 可以作用在类上也可以作用在方法上
@Service
public class UserService {
@Autowired
private UserDao userDao;
//实现转钱
public void accountMoney() throws Exception{
//lucy 少 100
userDao.redMoney();
Integer i=1/0;
//mary 多 100
userDao.addMoney();
}
}
i=1/0模拟异常情况
准备数据库
如果不加入事物我们在进行转账的时候就会发生 1001用户减少了金额但是1002用户没有增加金额的情况,所以我们在service添加事物如果发生了异常 那么2个dao层的操作都会不进行。
xml文件配置
6.4事务操作(声明式事务管理参数配置)
1、在 service 类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数、
2.propagation:事务传播行为
直接在注解中添加
场景演示
6.5事务操作(XML 声明式事务管理)
配置xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- 1.创建事物管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2.配置通知-->
<tx:advice id="txadvice">
<!-- 配置事物参数-->
<tx:attributes>
<!-- 指定在哪个方法加事物,确定事物的类型规则-->
<tx:method name="accountMoney" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 3.配置切入点和切面-->
<aop:config>
<!-- 切入点、、-->
<aop:pointcut id="tx" expression="execution(* com.spring5.service.UserService.*(..))"/>
<!-- 切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="tx"/>
</aop:config>
<!-- 数据库连接池 -->
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClass}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.userName}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
</beans>
删除事物的注解进行测试