Spring5 框架
目录内容
- Spring概念
- IOC容器
- Aop
- JdbcTemplate
- 事务管理
- Spring5新特性
Spring
1. Spring 框架是一个轻量级的开源的JavaEE框架。
2. 解决企业应用开发的复杂
3. Spring有两个核心部分: IOC和AOP
1. IOC : 控制反转,把创建对象的过程交给Spring进行管理
2. AOP: 面向切面,不修改源代码进行功能增强。
4. Spring特点
1. 方便解耦,简化开发
2. AOP编程支持
3. 方便程序的测试
4. 方便继承其它框架,Mybatias等
5. 方便进行实务操作
6. 降低API的使用难度
5. Spring5.x
入门案例
下载地址
- 导入jar包
core container
- bean
- context
- express
- core
1 创建一个普通的类
public class User {
public void add(){
System.out.println("add....");
}
}
创建Spring 配置文件
- 首先在src下创建一个 xml文件 ,bean1.xml.
- 注意是右键,然后new xml 配置文件
<bean id="user" class="com.atguigu.spring5.User">
</bean>
-
进行测试
@Test public void testAdd(){ // 1. 加载spring 配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml") ; // 2. 获取配置创建文件 User user = (User) context.getBean("user", User.class) ; System.out.println(user); user.add(); }
2 IOC容器(*****)
- IOC底层原理
- IOC接口 (BeanFactory)
- IOC操作Bean 管理(基于xml)
- IOC操作Bean管理(基于注释)
什么是IOC?
- 控制反转 ,把对象的创建和对象之间的调用过程,交给Spring'进行管理
- 使用的目的 : 为了降低耦合度
- 做入门的案例就是IOC的实现
IOC的底层原理
- xml的解析 , 工厂模式 ,反射
画图流程
原始方式
class UserService {
execute () {
UserDao dao = new UserDao();
dao.add() ;
}
}
class UserDao{
add(){
....
}
}
在userService=里面调用dao的方法
工厂模式
创建一个工厂模式 ,将对象的创建和方法调用分开 ,实现解耦合
Class UserFactory{
public static UserDao getDao(){
return new UserDao() ;
}
}
// userservice 也相应的变化
class UserService{
execute{
User dao = UserFactory.getDao() ;
dao.add() ;
}
}
目的 : 耦合度降低到最低限度
IOC过程
-
第一步配置 xml文件,配置创建对象
<bean id="dao" class="com.atguigu.spring5.UserDao"> </bean>
-
第二部 有service 了和dao类 ,创建工程类
Class UserFactory{
public static UserDao getDao(){
Class.forName();
}
}
IOC(接口)
-
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
-
Spring 提供IOC容器实现两种方式
-
BeanFactory : IOC容器基本实现 ,是Spring内部的使用接口
加载配置文件的时候不去创建对象,而在获取对象采取创建对象
-
ApplicationContest :BeanFactory 接口的子接口
加载配置文件的时候就会在配置文件对象进行创建
-
-
ApplicationContext接口的实现
IOC操作Bean管理
-
什么是Bean管理
- Spring 创建对象
- Spring 注入属性
-
Bean 管理操作的两种方式
-
基于xml配置文件实现
-
基于注解
-
基于xml配置文件实现
<bean id="user" class="com.atguigu.spring5.User"></bean>
- bean标签的属性
- id 属性 :别名
- class属性 : 类全路径
- 创建对象的时候,默认是执行无参数构造方法进行对象的创建
基于xml方式注入属性
-
DI :依赖注入,就是注入属性
两种注入基本方式 :
-
set方法进行注入
public class Book { private String bname ; public void setBname(String bname) { this.bname = bname; } public void testDemo(){ System.out.println(bname); } public static void main(String[] args) { Book book = new Book() ; book.setBname("adoad"); } }
<bean id="book" class="com.atguigu.spring5.Book"> <property name="bname" value="图书"></property> </bean>
测试
@Test public void testBook(){ // 1. 加载spring 配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml") ; // 2. 获取配置创建文件 Book book = context.getBean("book" , Book.class) ; 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 orderTest(){ System.out.println(oname + address); } }
<bean id="order" class="com.atguigu.spring5.Orders"> <constructor-arg name="oname" value="订单名称"></constructor-arg> <constructor-arg name="address" value="地址"></constructor-arg> </bean>
-
-
P名称空间注入
-
使用p名称可以简化
(1) 第一步添加p名称空间在配置文件中‘
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" // p空间声明 xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
(2) 第二部在bean中进行操作
<bean id="book" class="com.atguigu.spring5.Book" p:bname="几样神功" > <!-- <property name="bname" value="图书"></property>--> </bean>
-
IOC操作Bean管理 (xml注入其他)
- 字面量
(1) 设置属性 null 值
//class 类
public class Book {
private String bname ;
private String address ;
public void setAddress(String address) {
this.address = address;
}
public void setBname(String bname) {
this.bname = bname;
}
public void testDemo(){
System.out.println("bname : " +bname);
System.out.println("address :" +address);
}
}
// 配置bean 将属性adress设置为null
<bean id="book" class="com.atguigu.spring5.Book" >
<property name="bname" value="图书"></property>
<property name="address" >
<null/>
</property>
</bean>
// 测试
@Test
public void testBook(){
// 1. 加载spring 配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml") ;
// 2. 获取配置创建文件
Book book = context.getBean("book" , Book.class) ;
book.testDemo();
}
(2) 属性值中包含特殊符号
<property name="address">
<value><![CDATA[南京]]></value>
</property>
注入属性 -外部bean
- 创建两个类 service 和 dao 类
- 在service调用dao的方法
public class UserService {
private UserDao userDao ;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add ...");
}
}
配置bean
<!-- service -->
<bean id="userService" class="com.atguigu.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- dao -->
<bean id="userDao" class="com.atguigu.dao.impl.UserDaoImpl"></bean>
测试
@Test
public void testService(){
// 加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml") ;
//
UserService service = context.getBean("userService",UserService.class) ;
service.add();
}
注入属性-内部bean 和级联赋值
创建2个类 ,员工类和部门类
// 员工
public class Emp {
private String ename ;
private String gender ;
private Dept dept ; // 员工所属部门
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public void add() {
System.out.println(" ename : " + ename) ;
System.out.println("gender : " +gender);
System.out.println("dept : " + dept);
}
}
// 部门类
public class Dept {
private String dname ;
public void setDname(String dname) {
this.dname = dname;
}
@Override
public String toString() {
return "["+dname+"]" ;
}
}
内部bean配置
<!-- 内部bean-->
<bean id="emp" class="com.atguigu.bean.Emp">
<property name="ename" value="zhs"></property>
<property name="gender" value="男"></property>
<property name="dept">
<bean id="Dept" class="com.atguigu.bean.Dept">
<property name="dname" value="安保部门"></property>
</bean>
</property>
</bean>
注入属性 - 级联赋值
第一种写法
<bean id="emp" class="com.atguigu.bean.Emp">
<property name="ename" value="zhs"></property>
<property name="gender" value="男"></property>
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.atguigu.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
第二种写法
<bean id="emp" class="com.atguigu.bean.Emp">
<property name="ename" value="zhs"></property>
<property name="gender" value="男"></property>
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="技术部门"></property>
</bean>
同时在 Emp中增加一个 get方法
public Dept getDept() {
return dept;
}
IOC操作 Bean管理 (xml注入 集合属性)
- 注入数组类型
- 注入List类型
- 注入Map类型
- 注入Set类型
上面这四种一起写在一个类中进行注入
public class Stu {
private String [] course ;
private List<String> list ;
private Map<String ,String > maps ;
private Set<String> sets ;
public void setCourse(String[] course) {
this.course = course;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void test() {
System.out.println(Arrays.toString(course));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
}
}
<bean id="stu" class="com.atguigu.bean.Stu">
// 数组的注入
<property name="course">
<array>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</array>
</property>
// list 类型注入
<property name="list">
<list>
<value>list1_value</value>
<value>list2_value</value>
</list>
</property>
// map注入
<property name="maps">
<map>
<entry key="JAVA" value="90"></entry>
<entry key="Python" value="98"></entry>
</map>
</property>
<property name="sets">
<set>
<value>Mysql</value>
<value>Mybatis</value>
</set>
</property>
</bean>
@Test
public void testStu() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml") ;
Stu stu = context.getBean("stu", Stu.class) ;
stu.test();
}
在集合里面设置一个对象类型的值
-
首先在Stu类中增加一个属性 List
111 private List<Course> courseList ; public void setCourseList(List<Course> courseList) { this.courseList = courseList; }
-
在xml中配置bean
// 在 Stu的bean中增加 property <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property>
<bean id="course1" class="com.atguigu.bean.Course"> <property name="cname" value="spring框架"></property> </bean> <bean id="course2" class="com.atguigu.bean.Course"> <property name="cname" value="pytornc框架"></property> </bean>
把集合注入的部分提取出来
-
在spring配置里面引入名称空间util
<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">
-
使用util标签完成list集合注入提取
<!-- 提取list集合类型注入--> <util:list id="bookList"> <value>java基础</value> <value>机器学习</value> </util:list> <!-- 使用--> <bean id="book" class="com.atguigu.bean.Book"> <property name="list" ref="bookList"> </property> </bean>
IOC操作 Bean管理(FactoryBean)
- Spring 有两种 bean , 一个是普通的bean ,一个工厂bean
- 普通bean : 在配置文件中定义的是什么类型就返回类型
- 工厂bean : 可以和返回类型不同
IOC操作 Bean管理(FactoryBean)
-
spring中 ,默认是单实例对象 , 配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
-
scope属性值
第一个值 默认 singleton 单实例
第二个值 prototype 多实例
-
singleton 和 prototype 区别
- 在设置singleton 时, 加载spring配置文件的时候就会创建单实例对象
- 设置 prototype时候 , 不是加载spring配置文件的时候创建,在调用getBean方法的时候创建多实例对象。
-
request 和 respone 创建bean时放在 requese域内
IOC操作 Bean管理(生命周期)
- 生命周期 : 从对象创建到对象的销毁
- bean 的生命周期 :
- 通过构造器创建bean实例
- 为bean的属性设置值和对其他bean引用 (调用set方法)
- 调用bean的初始化的方法(需要配置 )
- bean可以使用了(对象获取)
- 当容器关闭时候,调用bean 的销毁的方法
类
public class Orders {
private String oname ;
public Orders() {
System.out.println("(1)无参构造 ,创建bean实例对象");
}
public void setOname(String oname) {
System.out.println("(2)注入属性值");
this.oname = oname;
}
//创建执行初始方法
public void initMethod() {
System.out.println("(3)第三步初始化方法 ");
}
//销毁
public void destroyMethod() {
System.out.println("(5) 执行销毁");
}
}
配置
<bean id="orders" class="com.atguigu.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="吃灰"></property>
</bean>
测试
@Test
public void testOrder() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml") ;
Orders orders = (Orders) context.getBean("orders", Orders.class) ;
System.out.println("(4) 第四部 对象获取到了");
context.close();
}
输出
(1)无参构造 ,创建bean实例对象 (2)注入属性值 (3)第三步初始化方法 (4) 第四部 对象获取到了 (5) 执行销毁
bean的后置处理器
- 通过构造器创建bean实例
- 为bean的属性设置值和对其他bean引用 (调用set方法)
- 把bean实例传递Bean后置处理方法
- 调用bean的初始化的方法(需要配置 )
- 把bean实例传递Bean后置处理方法
- bean可以使用了(对象获取)
- 当容器关闭时候,调用bean 的销毁的方法
创建一个 mybeanposy
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
<bean id="mybeanpost" class="com.atguigu.bean.MyBeanPost"></bean>
IOC操作 Bean管理(自动装配)
- 什么是自动装配
- 根据指定的装配规则(属性名称或者属性类型) ,spring自动将匹配的属性值进行注入
- 演示自动转配的过程
-
根据属性名称进行注入
<bean id="emp" class="com.atguigu.bean.Emp" autowire="byName"> </bean>
IOC操作 Bean管理(外部属性文件)
-
直接配置数据库信息 (德鲁伊数据连接池)
-
在xml中增加context命名空间
-
在xml中配置
<context:property-placeholder location="classpath:jdb.properties"/>
<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>
-
在src下创建 jdbc.propreties
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/bookdb?useUnicode=true&characterEncoding=utf-8&useSSL=false jdbc.username=root jdbc.password=100200s+o2=so2
-
IOC操作Bean管理 (基于注解方式)
- 什么是注解?
- 注解是代码的特殊标记, @xxx( 属性名 =属性值 )
- 使用注解 ,注解作用在类上面,方法上面,属性上面
- 目的注解: 简化xml配置。
- Spring 针对Bean管理中创建的对象提供注解
- @Component
- @Service
- @Controller
- @Repository
- 上面的四个注解都是用来创建bean 实例
基于注解方式创建对象
-
引入aop依赖
-
开启组件扫描
<!-- 开启组件扫描--> <context:component-scan base-package="com.atguigu"></context:component-scan>
// 在注解里面的value属性也可以省略 // UserService -> userService @Component(value = "userService" ) // == <bean id = "userService class= " ... public class UserService { public void add() { System.out.println("service add ----"); } }
<!-- 实例1 use-default-filters 是false 则不使用默认的filter context :include-filter 设置扫描哪些内容 --> <context:component-scan base-package="com.atguigu" use-default-filters="false"> <!-- 只扫描带Controller 的包--> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <context:component-scan base-package="com.atguigu" > <!-- 除了Controller 的包 ,其他的都扫描--> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
基于注解方式实现属性注入
-
@AutoWired : 根据属性类型进行自动配置
- 把service和dao对象创建 ,在service和dao类添加创建对象注解
- 在service注入dao对象 ,在service类添加dao类型属性,在属性上添加注解
-
@Qualifier :根据属性名进行注入
-
要和上面的AutoWired进行一起使用
@Autowired // 根据类型进行注入 @Qualifier("userDaoImpl1") // 如果接口有多个实现类,为了区分是哪个实现类,可以用这 private UserDao userDao ; public void add() { System.out.println("service add ----"); userDao.add(); }
@Repository("userDaoImpl1") public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("dao addd...."); } }
-
-
@Resource :可以根据属性名 也可以根据属性类型
@Resource(name = "userDaoImpl1") //根据属性名注入
-
@Values :
@Value(value = "zhs") private String name ;
对某个属性进行注入数值
完全注解开发
-
创建配置类 ,替换xml文件配置
@Configuration //作为配置类 @ComponentScan(basePackages = {"com.atguigu"}) // <context:component-scan base-package="com.atguigu"></context:component-scan> public class SpringConfig { }
-
创建测试
@Test public void testService3 () { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class) ; UserService userService = context.getBean("userService" , UserService.class) ; userService.add(); }
其中AnnotatioonConfigApplicationContext 加载配置类的字节码
AOP内容
AOP基本概念
什么是AOP?
面向切面编程 ,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性。
底层原理
- AOP底层使用动态代理
- 有两种情况的动态代理
- 第一种 有接口的情况 使用JDK动态代理
- 创建UserDao的实现代理类,增强login方法
- 第二种没有接口情况 ,使用CLIB动态代理
- 创建类的子类,在子类中重写方法
- 如果用动态代理 :
- 创建当前类子类的代理对象
AOP(JDK 动态原理 )
- 调用 newProxyInstace 方法
- 方法的参数 :
- 第一个参数 : 类加载器
- 第二个参数 : 增强方法所在的类,这类实现的接口,支持多个接口
- 第三个参数: 实现这个接口InvocationHandler,创建代理对象,写增强方法
- 方法的参数 :
- 代码实现
- 创建接口实现类
接口实现类
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id ;
}
}
2 创建接口实现类代理
代理类
public class JDKProxy {
public static void main(String[] args) {
// 创建接口实现类代理对象
Class [] interfaces = {UserDao.class} ;
UserDaoImpl userDao = new UserDaoImpl() ;
UserDao dao = (UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao) ) ;
int res = dao.add(1,2) ;
System.out.println(res );
}
}
创建代理对象,实现InvocationHandler接口
// 创建代理对象代码
class UserDaoProxy implements InvocationHandler{
// 吧创建的是谁的代理对象,吧谁传递过来
// 通过有参数构造获得 想要增强的接口实现类对象
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("方法执行之后");
return res;
}
}
method.getName 可以获得实现类里面的方法,然后进行判断去增强哪个方法。
AOP(术语)
-
连接点
- 哪些方法可以被增强,这些方法就是连接点
Class User { void add() ; void update(); }
比如add 方法可以被增强, 那么这就是一个连接点
-
切入点
- 实际被真正增强的方法就是切入点。
-
通知(增强)
- 实际增强的逻辑部分称为通知
- 5种类型的通知 、
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知 finally
-
切面
把通知应用到切入点的过程
AOP操作
-
Spring 框架一般都是基于AspectJ实现AOP操作
- 什么是AspectJ ?
- AspectJ 不是Spring组成部分 ,独立AOP框架,一般吧AspectJ和Spring框架一起使用,进行AOP操作。
- 什么是AspectJ ?
-
基于AspectJ实现AOp操作
- 基于xml配置文件实现
- 以及注解方式实现(一般使用这个)
-
在项目工程中引入AOp相关的依赖
-
切入点的表达式
-
作用 :知道对那个类里面的哪个方法进行增强
-
语法结构 :
execution( [权限修饰符] [ 返回类型] [类全路径] [方法名称] [ 参数列表] )
权限修饰符可以省略 , 但是返回类型为必填
- 举例 : 对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.* . *(..))
-
AOP操作(基于AspectJ注解 )
-
创建类, 在类里面进行增强
public class User { public void add() { System.out.println("addd "); } }
2 . 创建增强类
public class UserProxy {
// 前置通知
public void before() {
System.out.println("before -- -- ");
}
}
3 . 通知的配置
- 在spring配置文件中,开启注解扫描
- 使用注解创建User 和 UserProxy对象
- 在增强的类上面添加注解 @Aspect
- 在spring 配置文件中开启生成代理对象
前置通知应用
(1) 首先开启注解扫描 , context:component-scan
<?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"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.atguigu.Spring5.aopanno"></context:component-scan>
</beans>
(2)使用注解创建User 以及UserProxy对象
使用Component 注解
@Component
public class User {
public void add() {
System.out.println("addd ");
}
}
@Component
public class UserProxy {
public void before() {
System.out.println("before -- -- ");
}
}
(3) 在增强的类上面添加注解 @Aspect
@Component
@Aspect
public class UserProxy {
public void before() {
System.out.println("before -- -- ");
}
}
(4) 在代理对象的前置通知上面添加注解 @before (表达式 )
// 前置通知
@Before(value = "execution(* com.atguigu.Spring5.aopanno.User.add(..))")
public void before() {
System.out.println("before -- -- ");
}
(5)在spring 配置文件中开启生成代理对象
<!-- 开启AspectJ 生成代理对象-->
<aop:aspectj-***></aop:aspectj-***>
配置不同类型的通知
- 前置通知 ,后置通知 , 环绕通知(在增强方法前和后执行) ,等
@Component
@Aspect
public class UserProxy {
// 前置通知
@Before(value = "execution(* com.atguigu.Spring5.aopanno.User.add(..))")
public void before() {
System.out.println("before -- -- ");
}
// 后置通知
@After(value = "execution(* com.atguigu.Spring5.aopanno.User.add(..))")
public void after() {
System.out.println("after ---- ");
}
// 返回结果之后才执行
@AfterReturning(value = "execution(* com.atguigu.Spring5.aopanno.User.add(..))")
public void afterRetuing() {
System.out.println("after retuing ");
}
// 异常通知
// 被增器方法有异常才执行
@AfterThrowing(value = "execution(* com.atguigu.Spring5.aopanno.User.add(..))")
public void afterthrowing() {
System.out.println("afterthrowing ");
}
// 环绕通知
@Around(value = "execution(* com.atguigu.Spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知 之前 ");
proceedingJoinPoint.proceed() ; // 执行增强方法
System.out.println("环绕通知之后 ");
}
}