Spring 5 框架【完整版】
- Spring 5 框架
-
- 一、Spring 简介
-
- 1、Spring特点
- 2、下载spring5资源
-
- 1-百度网盘
- 2-网页下载
- 3、入门案例
-
- 1.案例一(入门)
- 二、IOC容器
-
- 1、什么是IOC(概念和原理)
-
- 1.1、什么是IOC(控制反转)
- 1.2、 IOC底层
- 1.3、IOC底层原理过程
- 2、IOC(接口)
- 3、IOC操作Bean管理
-
- 3.1、什么是Bean管理
- 3.2、Bean管理操作有两种工作方式
-
- (1)基于xml配置文件方式实现
- (2)基于注解方式实现
- 4、IOC操作Bean管理( 基于xml配置文件方式 )
-
- 4.1、基于XML方式创建对象
- 4.2、基于XML方式注入属性
- 4.3、第一种注入方式:使用set方法
- 4.4、第二种注入方式:有参构造注入
- 4.5、第三种注入方式,p名称空间注入,可以简化基于xml配置方式。(了解)
- 5、IOC操作Bean管理( xml方式注入其他类型属性 )
-
- 5.1、字面量--NULL值
- 5.2、字面量--属性包含特殊符号
- 5.3、注入属性-外部Bean
- 5.4、注入属性-内部Bean
- 5.5、注入属性-级联赋值
- 6、IOC操作Bean管理( xml方式注入集合属性 )
-
- 6.1、注入数组类型属性
- 6.2、注入List集合类型属性
- 6.3、注入Map集合类型属性
- 6.4、注入set集合类型属性
- 6.5、注入对象集合类型属性
- 6.6、把集合注入部分提取出来
- 7、 IOC操作Bean管理(FactoryBean )
- 8、 IOC操作Bean管理(Bean 的作用域)
- 9、 IOC操作Bean管理(Bean 生命周期)
- 10、IOC操作Bean管理(XML自动装配 )
-
- 10.1、什么是自动装配
- 10.2、自动装配过程
- 11、IOC操作Bean管理(外部属性文件 )
-
- 11.1、方式一:直接配置数据库信息
- 11.2、方式二:引入外部属性文件配置数据库连接池
- 12、IOC操作Bean管理(基于注解方式 )
-
- 12. 1、什么是注解
- 12. 2、Spring 针对 Bean 管理中创建对象提供注解
- 12. 3、基于注解方式实现 -对象创建
- 12. 4、开启组件扫描细节配置
- 12. 5、基于注解方式实现 -属性注入
- 12. 6、基于注解方式实现 -对象创建和属性注入(案例1,xml配置)
- 12. 7、完全注解开发(案例2,配置类)
- 三、AOP
-
- 1、AOP (概念)
-
- 1.1、AOP基本概念
- 1.2、 AOP登录案例说明
- 2、AOP (底层原理)
-
- 2.1、AOP 底层使用动态代理 (动态代理有两种情况):
- 3、AOP(JDK 动态代理)
-
- 3.1、使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象
- 3.2、编写 JDK 动态代理代码
- 4、AOP(术语)
-
- (a)连接点:类里面哪些方法可以被增强,这些方法称为连接点
- (b)切入点:实际被真正增强的方法称为切入点
- (c)通知(增强):实际增强的逻辑部分称为通知,且分为五种类型
- (d)切面:把通知应用到切入点过程**
- 5、AOP操作(准备)
-
- 5.1、Spring框架一般都是基于Aspect]实现AOP操作
- 5.2、基于Aspect1实现AOP操作
- 5.3、在AOP项目中引入jar包
- 5.4、切入点表达式
- 6、AOP操作(AspectJ注解)
-
- 6.1、创建类,在类里面定义方法
- 6.2、创建增强类(编写增强逻辑)
- 6.3、进行通知的配置
- 6.4、配置不同类型的通知
- 6.5、相同的切入点抽取
- 7、AOP操作(有多个增强类,优先级)
- 8、AOP操作(AspectJ配置文件---了解)
-
- 8.1、创建两个类,增强类和被增强的类,并且创建方法
- 8.2、xml配置文件创建两个类对象
- 8.3、在 spring 配置文件中配置切入点
- 四、JdbcTemplate
-
- 1、JdbcTemplate概念及使用
-
- 1.1、什么是JdbcTemplate
- 1.2、准备工作
-
- - (1)引入jar包
- - (2)引入数据库连接池
- - (3)配置 JdbcTemplate 对象,注入 DataSource
- - (4)配置文件
- 2.添加、修改、删除操作
-
- 2.1、添加操作
- 2.2、修改操作
- 2.3、删除操作
- 2.4、实现案例
-
- - (5)创建 service 类,创建 dao 类,在 dao 注入 jdbcTemplate 对象
- - (6)测试
- 五、事务管理
Spring 5 框架
一、Spring 简介
1、Spring特点
- Spring是轻量级的开源的JavaEE,框架
- Spring可以解决企业应用开发的复杂性。
-
Spring有两个核心部分:IOC和 Aop
(1) IOC:控制反转,把创建对象过程交给Spring进行管理
(2) Aop:面向切面,不修改源代码进行功能增强
-
Spring特点
(1) 方便解耦,简化开发
(2) Aop编程支持·
(3) 方便程序测试,
(4) 方便和其他框架进行整合
(5) 方便进行事务操作,
(6)降低API开发难度
2、下载spring5资源
1-百度网盘
链接:https://pan.baidu.com/s/1LqEl6jD96etBQYFT1voMfg
提取码:zp4h
2-网页下载
主要就是一些资源jar包等等
-
spring官网
https://spring.io/
- Projects----->Spring Framework
- 选择LEARN(GA稳定版本)
- 聪给GitHub中下载
- Access
-
Downloading a Distribution
(https://repo.spring.io)
- https://repo.spring.io
- https://repo.spring.io/release/org/springframework/spring/
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210514205518288.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xqZjE5MDQwOQ==,size_16,color_FFFFFF,t_70
3、入门案例
导入基本spring的jar包
1.案例一(入门)
- 创建类 Main
package com.company.demo1;
public class Main {
public void add(){
System.out.println("add.......");
}
}
- 创建配置文件XML spring5_demo1.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.配置文件Main对象的创建-->
<bean id="main" class="com.company.demo1.Main"></bean>
</beans>
- 创建测试类 TestSpring5
public class TestSpring5 {
@Test
public void testMain(){
//1.加载spring配置文件,两种接口
// BeanFactory(父类)/ApplicationContext(子类)
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo1.xml");
//2.获取配置文件的对象
Main main=context.getBean("main",Main.class);
//输出类的对象
System.out.println(main);
//输出方法信息
main.add();
}
}
- 测试结果
二、IOC容器
(1)、IOC底层原理
(2)、IOC接口( BeanFactory)
(3)、IOC操作 Bean管理(基于xml)
(4)、IOC操作Bean管理(基于注解)
1、什么是IOC(概念和原理)
1.1、什么是IOC(控制反转)
a)把对象创建和对象之间的调用过程,交给Spring进行管理
b)使用IOC目的:为了降低耦合度
1.2、 IOC底层
a)xml解析、工厂模式、反射
1.3、IOC底层原理过程
2、IOC(接口)
- IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
-
Spring 提供IOC容器实现两种方式:(两个接口)。
a)BeanFactory接口:
-----IOC容器基本实现,是Spring内部接口的使用接口,不提供给开发人员进行使用(加载配置文件时候不会创建对象,在获取对象时才会创建对象。)
b)ApplicationContext接口:
-----BeanFactory接口的子接口,提供更多更强大的功能,提供给开发人员使用(加载配置文件时候就会把在配置文件对象进行创建)
//1.加载spring配置文件,两种接口 // BeanFactory(父类) / ApplicationContext(子类) ApplicationContext context= new ClassPathXmlApplicationContext("spring5_demo1.xml"); //2.获取配置文件的对象 Main main=context.getBean("main",Main.class);
- ApplicationContext接口的实现类
3、IOC操作Bean管理
3.1、什么是Bean管理
(1)Bean管理就是两个操作:
(2)Spring创建对象;
(3)Spring注入属性;
3.2、Bean管理操作有两种工作方式
(1)基于xml配置文件方式实现
(2)基于注解方式实现
4、IOC操作Bean管理( 基于xml配置文件方式 )
4.1、基于XML方式创建对象
<!--1.配置文件Main对象的创建-->
<bean id="main" class="com.company.demo1.Main"></bean>
- (1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
- (2)在bean标签有很多属性,介绍常用的属性
- id属性:唯一标识
- class属性:类的路径(包类路径)
- (3)创建对象时候,默认也是执行无参数构造方法v
4.2、基于XML方式注入属性
-
DI : 依赖注入,就是注入属性
a : 第一种注入方式:使用set方法
b : 第二种注入方式:有参构造注入
c : p名称空间注入,可以简化基于xml配置方式。(了解)
4.3、第一种注入方式:使用set方法
案例:
/*
*实体类
*/
public class Book {
private String bname;
private String ba;
private String address;
//set方法注入
public void setBname(String bname) {
this.bname = bname;
}
public void setBa(String ba){
this.ba = ba;
}
public void setAddress(String address) {
this.address = address;
}
//输出结果
public void add1(){
System.out.println(bname+"::"+ba+"::"+address);
}
}
<!-- 配置文件-->
<?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">
<!-- 2.set方法注入属性-->
<bean id="book" class="com.company.demo1.Book">
<!-- 使用property完成属性的注入
name:类里面的属性名称
value:向属性注入的值
-->
<property name="bname" value="易筋经"></property>
<property name="ba" value="老子"></property>
<!-- NUll值 -->
<!-- <property name="address">-->
<!-- <null></null>-->
<!-- </property>-->
<!-- 属性值包含特殊符号 value="<<南京>>"
1.把<>进行转义<>
2.把带特殊符号内容写入CDATA
-->
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
</bean>
</beans>
/*
* 测试类
*/
@Test
public void testBook(){
//1.加载spring配置文件,两种接口
// BeanFactory(父类)/ApplicationContext(子类)
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo1.xml");
//2.获取配置文件的对象
Book book= context.getBean("book",Book.class)
System.out.println(book);
book.add1();
}
4.4、第二种注入方式:有参构造注入
案例:
/*
*实体类
*/
package com.company.demo1;
public class Orders {
private String oname;
private String address;
public Orders(String oname, String address) {
this.oname = oname;
this.address = address;
}
public void add(){
System.out.println(oname+"::"+address);
}
}
<!-- 配置文件-->
<!-- 3.有参构造注入属性-->
<bean id="orders" class="com.company.demo1.Orders">
<constructor-arg name="oname" value="abc"></constructor-arg>
<constructor-arg name="address" value="China"></constructor-arg>
</bean>
/*
* 测试类
*/
@Test
public void testOrders(){
//1.加载spring配置文件,两种接口
// BeanFactory(父类)/ApplicationContext(子类)
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo1.xml");
//2.获取配置文件的对象
Orders orders= context.getBean("orders",Orders.class);
System.out.println(orders);
orders.add();
}
4.5、第三种注入方式,p名称空间注入,可以简化基于xml配置方式。(了解)
<!--1、添加p名称空间在配置文件头部-->
<?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:p="http://www.springframework.org/schema/p" <!--在这里添加一行p-->
<!--2、在bean标签进行属性注入(算是set方式注入的简化操作)-->
<bean id="orders" class="com.company.demo1.Orders" p:oname="abc" p:address="China">
</bean>
5、IOC操作Bean管理( xml方式注入其他类型属性 )
5.1、字面量–NULL值
案例:
/*
*实体类
*/
public class Book {
private String bname;
private String ba;
private String address;
//set方法注入
public void setBname(String bname) {
this.bname = bname;
}
public void setBa(String ba){
this.ba = ba;
}
public void setAddress(String address) {
this.address = address;
}
//输出结果
public void add1(){
System.out.println(bname+"::"+ba+"::"+address);
}
}
<!-- 配置文件-->
<?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">
<!-- 2.set方法注入属性-->
<bean id="book" class="com.company.demo1.Book">
<!-- 使用property完成属性的注入
name:类里面的属性名称
value:向属性注入的值
-->
<property name="bname" value="易筋经"></property>
<property name="ba" value="老子"></property>
<!-- NUll值 -->
<property name="address">
<null></null>
</property>
</bean>
</beans>
/*
* 测试类
*/
@Test
public void testBook(){
//1.加载spring配置文件,两种接口
// BeanFactory(父类)/ApplicationContext(子类)
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo1.xml");
//2.获取配置文件的对象
Book book= context.getBean("book",Book.class)
System.out.println(book);
book.add1();
}
5.2、字面量–属性包含特殊符号
案例:
/*
*实体类
*/
public class Book {
private String bname;
private String ba;
private String address;
//set方法注入
public void setBname(String bname) {
this.bname = bname;
}
public void setBa(String ba){
this.ba = ba;
}
public void setAddress(String address) {
this.address = address;
}
//输出结果
public void add1(){
System.out.println(bname+"::"+ba+"::"+address);
}
}
<!-- 配置文件-->
<?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">
<!-- 2.set方法注入属性-->
<bean id="book" class="com.company.demo1.Book">
<!-- 使用property完成属性的注入
name:类里面的属性名称
value:向属性注入的值
-->
<property name="bname" value="易筋经"></property>
<property name="ba" value="老子"></property>
<!-- 属性值包含特殊符号 value="<<南京>>"
1.把<>进行转义<>
2.把带特殊符号内容写入CDATA
-->
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
</bean>
</beans>
/*
* 测试类
*/
@Test
public void testBook(){
//1.加载spring配置文件,两种接口
// BeanFactory(父类)/ApplicationContext(子类)
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo1.xml");
//2.获取配置文件的对象
Book book= context.getBean("book",Book.class)
System.out.println(book);
book.add1();
}
5.3、注入属性-外部Bean
<!--1 service和dao对象创建-->
<bean id="userService" class="com.company.demo2.service.UserService">
<!--注入userDao对象
name属性:类里面属性名称
ref属性:创建userDao对象bean标签id值
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.company.demo2.dao.UserDaoImpl"></bean>
- 创建两个类service类和dao类
- 在service调用dao里面的方法
- 在spring配置文件中进行配置,
案例:
package com.company.demo2.dao;
public interface UserDao {
public void update();
}
package com.company.demo2.dao;
public class UserDaoImpl implements UserDao {
@Override
public void update() {
System.out.println("dao update...........");
}
}
package com.company.demo2.service;
import com.company.demo2.dao.UserDao;
public class UserService {
//创建UserDao类型属性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add() {
System.out.println("service add...............");
userDao.update();//调用dao方法
}
}
<?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 -->
<!--1 service和dao对象创建-->
<bean id="userService" class="com.company.demo2.service.UserService">
<!--注入userDao对象
name属性:类里面属性名称
ref属性:创建userDao对象bean标签id值
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.company.demo2.dao.UserDaoImpl"></bean>
</beans>
@Test
public void testBean1(){
//1.加载spring配置文件
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo2.xml");
//2.获取配置创建的对象
UserService userService=context.getBean("userService",UserService.class);
userService.add();
}
5.4、注入属性-内部Bean
<bean id="emp" class="com.company.bean.Emp">
<!--设置两个普通属性-->
<property name="ename" value="Andy"></property>
<property name="gender" value="女"></property>
<!--设置对象类型属性-->
<property name="dept">
<bean id="dept" class="com.company.bean.Dept"><!--内部bean赋值-->
<property name="dname" value="宣传部门"></property>
</bean>
</property>
</bean>
一个部门有多个员工,一个员工对应一个部门。
案例:
package com.company.bean;
//部门类
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
@Override
public String toString() {
return "Dept{" +
"dname='" + dname + '\'' +
'}';
}
}
package com.company.bean;
//员工类
public class Emp {
private String ename;
private String gender;
//员工属于某一个部门,使用对象形式表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public Dept getDept() {
return dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void add(){
System.out.println(ename+"::"+gender+"::"+dept);
}
}
<?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 -->
<bean id="emp" class="com.company.bean.Emp">
<!--设置两个普通属性-->
<property name="ename" value="Andy"></property>
<property name="gender" value="女"></property>
<!--设置对象类型属性-->
<property name="dept">
<bean id="dept" class="com.company.bean.Dept"><!--内部bean赋值-->
<property name="dname" value="宣传部门"></property>
</bean>
</property>
</bean>
</beans>
@Test
public void testBean2(){
//1.加载spring配置文件
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo3.xml");
//2.获取配置创建的对象
Emp emp=context.getBean("emp", Emp.class);
emp.add();
}
5.5、注入属性-级联赋值
<!--方式一:级联赋值-->
<bean id="emp" class="com.company.bean.Emp">
<!--设置两个普通属性-->
<property name="ename" value="Andy"></property>
<property name="gender" value="女"></property>
<!--级联赋值-->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.company.bean.Dept">
<property name="dname" value="公关部门"></property>
</bean>
<!--方式二:级联赋值-->
<bean id="emp" class="com.company.bean.Emp">
<!--设置两个普通属性-->
<property name="ename" value="jams"></property>
<property name="gender" value="男"></property>
<!--级联赋值-->
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="技术部门"></property>
</bean>
<bean id="dept" class="com.company.bean.Dept">
</bean>
6、IOC操作Bean管理( xml方式注入集合属性 )
6.1、注入数组类型属性
<bean id="stu" class="com.company.demo1.Stu">
<!-- 数组类型属性注入 -->
<property name="courses">
<array>
<value>java课程</value>
<value>数据库课程</value>
</array>
</property>
6.2、注入List集合类型属性
<!--list类型属性注入-->
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
6.3、注入Map集合类型属性
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
6.4、注入set集合类型属性
<!--set类型属性注入-->
<property name="sets">
<set>
<value>MySql</value>
<value>Redis</value>
</set>
</property>
</bean>
案例:
package com.company.demo1;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
//(1)创建类,定义数组、list、map、set 类型属性,生成对应 set 方法
public class Stu {
//1 数组类型属性
private String[] courses;
//2 list集合类型属性
private List<String> list;
//3 map集合类型属性
private Map<String, String> maps;
//4 set集合类型属性
private Set<String> sets;
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void test(){
System.out.println(Arrays.toString(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
}
}
<?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="stu" class="com.company.demo1.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>
</beans>
package com.company.test;
import com.company.demo1.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.TestConstructor;
public class Test_demo1 {
@Test
public void test(){
//1.加载配置文件
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo1.xml");
//2.获取配置文件对象
Stu stu=context.getBean("stu",Stu.class);
stu.test();
}
}
6.5、注入对象集合类型属性
<bean id="stu" class="com.company.demo2.Stu">
<!-- 注入list集合类型的值,值是对象 -->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<!-- 创建多个course对象-->
<bean id="course1" class="com.company.demo2.Course">
<property name="cname" value="Spring框架"></property>
</bean>
<bean id="course2" class="com.company.demo2.Course">
<property name="cname" value="MYsql框架"></property>
</bean>
案例:
package com.company.demo2;
public class Course {
//课程名称
private String cname;
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course{" +
"cname='" + cname + '\'' +
'}';
}
}
package com.company.demo2;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
//(1)创建类,定义数组、list、map、set 类型属性,生成对应 set 方法
public class Stu {
//1 数组类型属性
private String[] courses;
//2 list集合类型属性
private List<String> list;
//3 map集合类型属性
private Map<String, String> maps;
//4 set集合类型属性
private Set<String> sets;
//学生所学多门课程
private List<Course> courseList;
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void test(){
System.out.println(Arrays.toString(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
System.out.println(courseList);
}
}
<?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="stu" class="com.company.demo2.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>
<!-- 注入list集合类型的值,值是对象 -->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<!-- 创建多个course对象-->
<bean id="course1" class="com.company.demo2.Course">
<property name="cname" value="Spring框架"></property>
</bean>
<bean id="course2" class="com.company.demo2.Course">
<property name="cname" value="MYsql框架"></property>
</bean>
</beans>
package com.company.test;
import com.company.demo2.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test_demo2 {
@Test
public void test(){
//1.加载配置文件
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo2.xml");
//2.获取配置文件对象
Stu stu=context.getBean("stu", Stu.class);
stu.test();
}
}
结果
6.6、把集合注入部分提取出来
-
(1)在spring配置文件中引入名称空间 util
xmlns:util=“http://www.springframework.org/schema/util”
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
<?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:p="http://www.springframework.org/schema/p"
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"
>
- (2)使用标签提取的list
案例:
package com.company.demo3;
import java.util.List;
public class Book {
//学生所学多门课程
private List<String> list;//创建集合
public void setList(List<String> list) {
this.list = list;
}
public void test(){
System.out.println(list);
}
}
<?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:p="http://www.springframework.org/schema/p"
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"
>
<!--1.提取list集合类型属性的注入-->
<util:list id="booklist">
<value>值一</value>
<value>值二</value>
<value>值三</value>
</util:list>
<!-- 2.使用提取的list-->
<!-- scope="prototype(多实例对象)/singleton(单实例对象)默认"
1,scope="singleton(单实例对象)默认",加载spring配置文件时候创建单实例对象
2,scope="prototype(多实例对象)",不是在加载spring配置文件时候创建对象,而是在调用getBean()方法时候创建多实例对象
-->
<bean id="book" class="com.company.demo3.Book" scope="prototype">
<property name="list" ref="booklist"></property>
</bean>
</beans>
package com.company.test;
import com.company.demo3.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test_demo3 {
@Test
public void test(){
//1.加载配置文件
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo3.xml");
//2.获取配置文件对象
Book book1=context.getBean("book", Book.class);
book.test();
System.out.println(book1);
}
}
7、 IOC操作Bean管理(FactoryBean )
- 1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
- 2、普通 bean:在配置文件中定义 bean 类型就是返回类型
- 3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
- 第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
- 第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
案例:工厂Bean
package com.company.demo4;
public class Course {
private String cname;
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course{" +
"cname='" + cname + '\'' +
'}';
}
}
package com.company.demo4;
import com.company.demo4.Course;
import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<Course> {
/*
* 工厂bean:在配置文件定义的bean类型和返回类型不一样
* 1.创建类,让这个类作为工厂bean,实现接口FactoryBean
* 2.在实现接口的方法里面定义放回的bean类型
* */
@Override
public Course getObject() throws Exception {
//定义返回bean
Course course;
course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
<?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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
>
<bean id="myBean" class="com.company.demo4.MyBean">
</bean>
</beans>
package com.company.test;
import com.company.demo4.Course;
import com.company.demo4.MyBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test_demo4 {
@Test
public void test4() {
ApplicationContext context =
new ClassPathXmlApplicationContext("spring5_demo4.xml");
Course course= context.getBean("myBean", Course.class);//返回值类型可以不是定义的bean类型!
System.out.println(course);
}
}
8、 IOC操作Bean管理(Bean 的作用域)
在 Spring 里面,默认情况下,bean 是单实例对象,
下面进行作用域设置:
- (1)在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
- (2)scope 属性值 第一个值 默认值,singleton,表示是单实例对象, 第二个值 prototype,表示是多实例对象
- (3)singleton 和 prototype 区别
a)singleton 单实例,prototype 多实例 b)设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象 ;设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建对象,在调用 getBean 方法时候创建多实例对象
9、 IOC操作Bean管理(Bean 生命周期)
- 1、生命周期 :从对象创建到对象销毁的过程
- 2、bean 生命周期
(1)通过构造器 创建 bean 实例(无参数构造) (2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法) (3)调用 bean 的初始化的方法(需要进行配置初始化的方法) (4)bean 可以使用了(对象获取到了) (5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
- 3、演示 bean 生命周期 :
public class Orders {
private String oname;
//无参数构造
public Orders() {
System.out.println("第一步 执行无参数构造创建 bean 实例");
}
//set方法
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 调用 set 方法设置属性值");
}
//创建执行的初始化的方法
public void initMethod() {
System.out.println("第三步 执行初始化的方法");
}
//创建执行的销毁的方法
public void destroyMethod() {
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参数配置-->
<!--配置初始化方法和销毁方法
初始化方法 init-method="initMethod"
销毁方法 destroy-method="destroyMethod"
-->
<bean id="orders" class="com.company.demo6.Orders" init-method="initMethod" destroy-method="destroyMethod">
<!--这里就是通过set方式(注入属性)赋值-->
<property name="oname" value="手机"></property>
</bean>
</beans>
public class Test_demo6 {
@Test
public void test(){
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring5_demo6.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步 获取创建 bean 实例对象");
System.out.println(orders);
//手动让 bean 实例销毁
context.close();
}
}
- 4、bean 的后置处理器,bean 生命周期有七步 (正常生命周期为五步,而配置后置处理器后为七步)
(1)通过构造器创建 bean 实例(无参数构造) (2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法) (3)*把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization* (4)调用 bean 的初始化的方法(需要进行配置初始化的方法) (5)*把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization* (6)bean 可以使用了(对象获取到了) (7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
在前面基础上添加
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;
}
}
<?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参数配置-->
<!--配置初始化方法和销毁方法
初始化方法 init-method="initMethod"
销毁方法 destroy-method="destroyMethod"
-->
<bean id="orders" class="com.company.demo6.Orders" init-method="initMethod" destroy-method="destroyMethod">
<!--这里就是通过set方式(注入属性)赋值-->
<property name="oname" value="手机"></property>
</bean>
<!--配置后置处理器-->
<bean id="myBeanPost" class="com.company.demo6.MyBeanPost"></bean>
</beans>
10、IOC操作Bean管理(XML自动装配 )
10.1、什么是自动装配
**根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入。**
10.2、自动装配过程
- (1)根据属性名称自动注入
- (2)根据属性类型自动注入
package com.company.demo5;
public class Emp {
public 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);
}
}
package com.company.demo5;
public class Dept {
@Override
public String toString() {
return "Dept{}";
}
}
<?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:p="http://www.springframework.org/schema/p"
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"
>
<!--实现自动装配
Bean标签里面autowire="byName"属性:
autowire="byName",根据名称注入,注入bean的id值和类里面属性名称一样
autowire="byType",根据类型注入,只能定义一个对象类型
-->
<bean id="emp" class="com.company.demo5.Emp" autowire="byName">
<!-- <property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.company.demo5.Dept"></bean>
</beans>
import com.company.demo5.Emp;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test_demo5 {
@Test
public void test(){
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo5.xml");
Emp emp=context.getBean("emp",Emp.class);
System.out.println(emp);
}
}
11、IOC操作Bean管理(外部属性文件 )
百度网盘-需要连接池jar包
链接:https://pan.baidu.com/s/1iWPMoRXHUfkoBfhgYu8g7Q
提取码:x9qm
11.1、方式一:直接配置数据库信息
(1)配置Druid(德鲁伊)连接池
(2)引入Druid(德鲁伊)连接池依赖 jar 包
<!--直接配置连接池-->
<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/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
11.2、方式二:引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties 格式文件,写数据库信息(jdbc.properties)
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/jdbc
prop.userName=root
prop.password=root
(2)把外部 properties 属性文件引入到 spring 配置文件中 —— 引入 context 名称空间
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
<!-- 引入外部属性文件properites-->
<context:property-placeholder location="classpath:jdbc.properitesd"></context:property-placeholder>
<!-- 配置连接池-->
<bean id="dataSource" class="com.alibab.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.username}"></property>
<property name="password" value="${prop.password }"></property>
</bean>
12、IOC操作Bean管理(基于注解方式 )
12. 1、什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化 xml 配置
12. 2、Spring 针对 Bean 管理中创建对象提供注解
下面四个注解功能是一样的,都可以用来创建 bean 实例
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
12. 3、基于注解方式实现 -对象创建
- 第一步 引入依赖 (引入spring-aop jar包)
链接:https://pan.baidu.com/s/1-S1KDjm4DkCtnygSFqzchA 提取码:414n
- 第二步 开启组件扫描
引入 context 名称空间 <!--二. 开启组件扫描 1.如果扫描多个包,多个包用逗号隔开 2.扫描包上层目录 --> <context:component-scan base-package="com.company.demo1"> </context:component-scan>
- 第三步 创建类,在类上面添加创建对象注解
//添加注解 ,value属性的值可以不写 //默认值是类名称,首字母小写 @Component(value = "userService")// <bean id="userService" class=""/> public class UserService { public void add(){ System.out.println("service add::::"); } }
12. 4、开启组件扫描细节配置
<!--示例1
use-default-filters="false”表示现在不使用默认filter,自己配置filtercontext:
context:include-filter ,设置扫描哪些内容
扫描base-package="com.company.demo1"这个包下面所有注解为@Controller的类(expression=" .Controller")
-->
<context:component-scan base-package="com.company.demo1" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例2
下面配置扫描包所有内容
context:exclude-filter:设置哪些内容不进行扫描
除了注解为@Controller的类(expression=" .Controller")不扫描,其他的类全部扫描
-->
<context:component-scan base-package="com.company.demo1" >
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
12. 5、基于注解方式实现 -属性注入
- (1)@Autowired:根据属性类型进行自动装配
- (2)@Qualifier:根据属性名称进行注入,这个@Qualifier 注解的使用,和上面@Autowired 一起使用
//2.和Autowired一起使用,根据名称注入属性 @Autowired @Qualifier(value = "userDaoImpl1")
- (3)@Resource:可以根据类型注入,也可以根据名称注入(它属于javax包下的注解,不推荐使用!)
//3.根据类型注入属性 @Resource //根据名称注入 @Resource(name = "userDaoImpl1") private UserDao userdao;
- (4)@Value:注入普通类型属性
//4.普通类型注入属性 @Value(value = "abc") private String name;
12. 6、基于注解方式实现 -对象创建和属性注入(案例1,xml配置)
- 接口
public interface UserDao {
public void add();
}
- 实现接口类1
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao{
@Override
public void add(){
System.out.println("UserDao add;;;;;");
}
}
- 实体类2
import com.company.demo1.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//添加注解 ,value属性的值可以不写
//默认值是类名称,首字母小写
//注解可以是@Repository/@Component/@Service/@Controller
@Service
@Component(value = "userService")// <bean id="userService" class=""/>
public class UserService {
//不需要添加set()方法
//添加注入属性注解
//1.根据类型注入属性 @Autowired
//2.和Autowired一起使用,根据名称注入属性
/* @Autowired
@Qualifier(value = "userDaoImpl1")
*/
//3.根据类型注入属性 @Resource
//根据名称注入
@Resource(name = "userDaoImpl1")
private UserDao userdao;
//4.普通类型注入属性
@Value(value = "abc")
private String name;
public void add(){
System.out.println(name);
System.out.println("service add::::");
userdao.add();
}
}
- 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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
>
<!--一.引用依赖jar包 spring-aop -->
<!--二. 开启组件扫描
1.如果扫描多个包,多个包用逗号隔开
2.扫描包上层目录
-->
<context:component-scan base-package="com.company.demo1">
</context:component-scan>
<!--三.创建类添加注解
(1) @Component
(2) @Service
(3) @Controller
(4)@Repository
-->
<!--示例1
use-default-filters="false”表示现在不使用默认filter,自己配置filtercontext:
context:include-filter ,设置扫描哪些内容
扫描base-package="com.company.demo1"这个包下面所有注解为@Controller的类(expression=" .Controller")
-->
<context:component-scan base-package="com.company.demo1" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例2
下面配置扫描包所有内容
context:exclude-filter:设置哪些内容不进行扫描
除了注解为@Controller的类(expression=" .Controller")不扫描,其他的类全部扫描
-->
<context:component-scan base-package="com.company.demo1" >
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
- 测试类
import com.company.demo1.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Vector;
public class TestDemo1 {
@Test
public void test(){
ApplicationContext context=
new ClassPathXmlApplicationContext("spring5_demo1.xml");
UserService userService=context.getBean("userService",UserService.class);
System.out.println(userService);
userService.add();
}
}
12. 7、完全注解开发(案例2,配置类)
** //这里就不需要XML配置文件,用@Configuration 作为配置类,代替XML配置文件**
- 配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration//作为配置类,代替XML配置文件
@ComponentScan(basePackages ={"com.company"})//组件扫描
public class Spring5Config_demo2 {
}
- 测试类
import com.company.demo1.config.Spring5Config_demo2;
import com.company.demo1.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo2 {
@Test
public void test(){
//这里就不需要XML配置文件,用@Configuration 作为配置类,代替XML配置文件
ApplicationContext context =
new AnnotationConfigApplicationContext(Spring5Config_demo2.class);
UserService userService=context.getBean("userService",UserService.class);
System.out.println(userService);
userService.add();
}
}
三、AOP
1、AOP (概念)
1.1、AOP基本概念
- (1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- (2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
1.2、 AOP登录案例说明
2、AOP (底层原理)
2.1、AOP 底层使用动态代理 (动态代理有两种情况):
- 第一种 有接口情况,使用 JDK 动态代理 ;创建接口实现类代理对象,增强类的方法
创建接口实现类代理对象,增强类的方法
- 第二种 没有接口情况,使用 CGLIB 动态代理;创建子类的代理对象,增强类的方法
创建子类的代理对象,增强类的方法。
3、AOP(JDK 动态代理)
3.1、使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象
- (1)调用 newProxyInstance 方法,方法有三个参数:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
第一参数,类加载器
第二参数,增强方法所在的类,这个类实现的接口,支持多个接口
第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分
3.2、编写 JDK 动态代理代码
- (1)创建接口,定义方法。
public interface UserDao {
public int add(int a,int b);
public String update(String id);
}
- (2)创建实现类,实现接口。
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id;
}
}在这里插入代码片
- (3)使用Proxy类创建接口代理对象
public class JDKProxy {
public static void main(String[] args) {
// Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
//创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
/**
第一参数,类加载器
第二参数,增强方法所在的类,这个类实现的接口,(支持多个接口)
第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分
*/
UserDao dao =(UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces,
new UserDaoProxy(userDao));
int result = dao.add(1, 2);
System.out.println("result:"+result);
}
}
//创建代理对象代码
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;
}
}
4、AOP(术语)
(a)连接点:类里面哪些方法可以被增强,这些方法称为连接点
(b)切入点:实际被真正增强的方法称为切入点
(c)通知(增强):实际增强的逻辑部分称为通知,且分为五种类型
1)前置通知
2)后置通知
3)环绕通知
4)异常通知
5)最终通知
(d)切面:把通知应用到切入点过程**
5、AOP操作(准备)
5.1、Spring框架一般都是基于Aspect]实现AOP操作
(1)什么是AspectJ
- AspectJ不是Spring组成部分,独立AOP框架,一般把 Aspect]和Spimg框架一起使用进行 AOP操作
5.2、基于Aspect1实现AOP操作
- (1) 基于xml配置文件实现
- (2)基于注解方式实现(使用),
5.3、在AOP项目中引入jar包
5.4、切入点表达式
- (1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
- (2)语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]) )
- (3)例子如下:
例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强 execution(* com.atguigu.dao.BookDao.add(..)) 例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强 execution(* com.atguigu.dao.BookDao.* (..)) 例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强 execution(* com.atguigu.dao.*.* (..))
6、AOP操作(AspectJ注解)
6.1、创建类,在类里面定义方法
//1、创建类,在类里面定义方法
public class User {
public void add() {
System.out.println("add.......");
}
}
6.2、创建增强类(编写增强逻辑)
//2、创建增强类(编写增强逻辑)
//(1)在增强类里面,创建方法,让不同方法代表不同通知类型
//增强的类
public class UserProxy {
public void before() {//前置通知
System.out.println("before......");
}
6.3、进行通知的配置
- (1)在spring配置文件中,开启注解扫描,
<!-- 开启注解扫描--> <context:component-scan base-package="Spring5_5.demo2"/>
- (2)使用注解创建User 和 UserProxy对象
//被增强的类 //1、创建类,在类里面定义方法 @Component public class User { public void add() { System.out.println("add......."); } }
- (3)在增强类上面添加注解@Aspect
//2、创建增强类(编写增强逻辑) //(1)在增强类里面,创建方法,让不同方法代表不同通知类型 //增强的类 @Component @Aspect//代理对象 public class UserProxy {
- (4)在spring配置文件中开启生成代理对象
<!-- 开启Aspect生成代理对象--> <aop:aspectj-autoproxy/>
6.4、配置不同类型的通知
- User
//被增强的类
//1、创建类,在类里面定义方法
@Component
public class User {
public void add() {
System.out.println("add.......");
}
}
- UserProxy
//2、创建增强类(编写增强逻辑)
//(1)在增强类里面,创建方法,让不同方法代表不同通知类型
//增强的类
@Component
@Aspect//代理对象
public class UserProxy {
//前置通知
@Before(value = "execution(* Spring5_5.demo2.User.add(..))")
public void before() {
System.out.println("before.........");
}
//最终通知
@After(value = "execution(* Spring5_5.demo2.User.add(..))")
public void after() {
System.out.println("after.........");
}
//后置通知(返回通知)
//有异常将不被执行
@AfterReturning(value = "execution(* Spring5_5.demo2.User.add(..))")
public void afterReturning() {
System.out.println("afterReturning.........");
}
//异常通知
//只有出现错误异常才会运行
@AfterThrowing(value = "execution(* Spring5_5.demo2.User.add(..))")
public void afterThrowing() {
System.out.println("afterThrowing.........");
}
//环绕通知
@Around(value = "execution(* Spring5_5.demo2.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前.........");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后.........");
}
}
- 没有异常
- 有异常
6.5、相同的切入点抽取
//2、创建增强类(编写增强逻辑)
//(1)在增强类里面,创建方法,让不同方法代表不同通知类型
//增强的类
@Component
@Aspect//代理对象
public class UserProxy {
//相同切入点抽取
@Pointcut(value = "execution(* Spring5_5.demo2.User.add(..))")
public void pointdemo() {
}
//前置通知
@Before(value = "pointdemo()")//相同切入点抽取使用!
public void before() {
System.out.println("before.........");
}
7、AOP操作(有多个增强类,优先级)
- 在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
//2、创建增强类(编写增强逻辑),同时对一个类中的方法增强 //增强的类1 @Component @Aspect @Order(1) public class Userproxy_2 { //增强的类2 @Component @Aspect//代理对象 @Order(3) public class UserProxy {
- Userproxy_2
//2、创建增强类(编写增强逻辑)
//(1)在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
@Component
@Aspect
@Order(1)
public class Userproxy_2 {
@Before(value = "execution(* Spring5_5.demo3.User.add())")
public void before(){
System.out.println("before................");
}
}
8、AOP操作(AspectJ配置文件—了解)
8.1、创建两个类,增强类和被增强的类,并且创建方法
//增强类
public class Book {
public void add() {
System.out.println("Book.add().......");
}
}
//被增强类
public class BookProxy {
//相同切入点抽取
@Pointcut(value = "execution(* Spring5_5.demo4.Book.add(..))")
public void pointdemo() {
}
//前置通知
@Before(value = "pointdemo()")//相同切入点抽取使用!
public void before() {
System.out.println("before.........");
}
}
8.2、xml配置文件创建两个类对象
<!--2. 创建对象-->
<bean id="book" class="Spring5_5.demo4.Book"/>
<bean id="bookProxy" class="Spring5_5.demo4.BookProxy"/>
8.3、在 spring 配置文件中配置切入点
<!--3、在 spring 配置文件中配置切入点-->
<!--配置 aop 增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* Spring5_5.demo4.Book.add(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
- Test
public class TestDemo4 {
@Test
public void test(){
ApplicationContext context= new ClassPathXmlApplicationContext("xml/Spring5_5/Spring5_demo4.xml");
Book book=context.getBean("book", Book.class);
book.add();
}
}
四、JdbcTemplate
1、JdbcTemplate概念及使用
1.1、什么是JdbcTemplate
Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作
1.2、准备工作
- (1)引入jar包
- (2)引入数据库连接池
<!-- 引入外部属性文件jdbc.properites-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 数据库连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<!-- <property name="url" value="jdbc:mysql://localhost:3306/jdbc?characterEncoding=utf-8&serverTimezone=UTC " />-->
<!-- <property name="username" value="root" />-->
<!-- <property name="password" value="root" />-->
<!-- <property name="driverClassName" value="com.mysql.jdbc.Driver" />-->
<property name="driverClassName" value="${driverClass}"/>
<property name="url" value="${url}"/>
<property name="username" value="${name}"/>
<property name="password" value="${password}"/>
</bean>
- (3)配置 JdbcTemplate 对象,注入 DataSource
<!--JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSoiure属性set方法-->
<property name="dataSource" ref="dataSource">
</property>
</bean>
- (4)配置文件
- jdbc.properties资源文件
driverClass=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbc?characterEncoding=utf-8&serverTimezone=UTC name=root password=root
- 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="Spring5_6"/> <!-- 引入外部属性文件jdbc.properites--> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 数据库连接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <!-- <property name="url" value="jdbc:mysql://localhost:3306/jdbc?characterEncoding=utf-8&serverTimezone=UTC " />--> <!-- <property name="username" value="root" />--> <!-- <property name="password" value="root" />--> <!-- <property name="driverClassName" value="com.mysql.jdbc.Driver" />--> <property name="driverClassName" value="${driverClass}"/> <property name="url" value="${url}"/> <property name="username" value="${name}"/> <property name="password" value="${password}"/> </bean> <!--JdbcTemplate对象--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 注入dataSoiure属性set方法--> <property name="dataSource" ref="dataSource"> </property> </bean> </beans>
2.添加、修改、删除操作
2.1、添加操作
//添加的方法
@Override
public void add(Book book){
//1.创建sql语句
String sql=" insert into jdbc.book(id, name, password) VALUES(?,?,?)";
//2.调用方法实现
Object[] args={book.getId(),book.getName(),book.getPassword()};
int update=jdbcTemplate.update(sql,args);
System.out.println(update);
}
2.2、修改操作
//修改的方法
@Override
public void update(Book book){
//1.创建sql语句
String sql="update jdbc.book set name=?,password=? where id=?";
//2.调用方法实现
Object[] args={book.getName(),book.getPassword(),book.getId()};
int update=jdbcTemplate.update(sql,args);
System.out.println(update);
}
2.3、删除操作
//删除的方法
@Override
public void delete(int id){
//1.创建sql语句
String sql=" delete from jdbc.book where id=?";
//2.调用方法实现
Object[] args={id};
int update=jdbcTemplate.update(sql,args);
System.out.println(update);
}
2.4、实现案例
- (5)创建 service 类,创建 dao 类,在 dao 注入 jdbcTemplate 对象
- *配置文件
<!-- 组件扫描 --> <context:component-scan base-package="Spring5_6"/>
- dao层接口
public interface BookDao { //添加方法 void add(Book book); //修改方法 void update(Book book); //删除方法 void delete(int id); }
- dao层实现接口
@Repository public class BookDaoImpl implements BookDao{ //注入JdbcTemlate @Autowired private JdbcTemplate jdbcTemplate; //添加的方法 @Override public void add(Book book){ //1.创建sql语句 String sql=" insert into jdbc.book(id, name, password) VALUES(?,?,?)"; //2.调用方法实现 Object[] args={book.getId(),book.getName(),book.getPassword()}; int update=jdbcTemplate.update(sql,args); System.out.println(update); } //修改的方法 @Override public void update(Book book){ //1.创建sql语句 String sql="update jdbc.book set name=?,password=? where id=?"; //2.调用方法实现 Object[] args={book.getName(),book.getPassword(),book.getId()}; int update=jdbcTemplate.update(sql,args); System.out.println(update); } //删除的方法 @Override public void delete(int id){ //1.创建sql语句 String sql=" delete from jdbc.book where id=?"; //2.调用方法实现 Object[] args={id}; int update=jdbcTemplate.update(sql,args); System.out.println(update); } }
- 实体类
//表数据属性实体类 public class Book { private int id; private String name; private String password; public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setPassword(String password) { this.password = password; } public int getId() { return id; } public String getName() { return name; } public String getPassword() { return password; } }
- Service层
@Service public class BookService { //注入dao @Autowired private BookDao bookDao; //添加操作 public void addBook(Book book) { bookDao.add(book); } //修改操作 public void updateBook(Book book){ bookDao.update(book); } //删除操作 public void deleteBook(int id){ bookDao.delete(id); } }
- (6)测试
public class Test_demo1 {
@Test
public void test(){
ApplicationContext context=new ClassPathXmlApplicationContext("xml/Spring5_6/spring5_demo1.xml");
BookService bookService=context.getBean("bookService", BookService.class);
Book book=new Book();
// //添加
// book.setId(11);
// book.setName("ljf12");
// book.setPassword("ljf1112");
// bookService.addBook(book);
// //修改
// book.setId(11);
// book.setName("ljf123");
// book.setPassword("ljf11123");
// bookService.updateBook(book);
// //删除
bookService.deleteBook(11);
}
}