## 步骤
1. 导入AOP约束(命名空间).
2. 配置目标对象.
3. 配置通知对象.
4. 配置将通知织入目标对象.
## 步骤
```
~~~
<!-- spring 中基于XML的AOP配置步骤
1.把通知Bean也交给spring来管理.
2.使用aop:config标签表名开始AOP的配置.
3.使用aop:aspect标签表名开始AOP的配置.
id属性:是给切面提供一个唯一标识.
ref属性:是指定通知类bean的ID.
4.在aop:aspect标签的内部使用对应标签来配置通知的类型.
我们现在示例是让通知类的方法在切入点方法执行之前执行,所以是前置通知.
aop:before :表示配置前置通知.
method属性:用于指定通知类中哪个方法是前置通知.
pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强
-->
~~~
```
## 代码
目标类:
~~~
public class UserServiceImpl implements UserService
{
@Override
public void save()
{
System.out.println("save");
}
@Override
public void delete()
{
System.out.println("delete");
}
@Override
public void update()
{
System.out.println("update");
}
@Override
public void get()
{
System.out.println("get");
}
@Override
public String toString()
{
return "UserServiceImpl{}";
}
}
~~~
通知类:
~~~
public class MyAdvice
{
//前置通知:目标方法运行之前调用
public void before()
{
System.out.println("前置通知");
}
//后置通知:如果出现异常不会调用
public void afterRunning()
{
System.out.println("后置通知,异常不调用");
}
//环绕通知:在目标方法之前和之后都调用
public Object around(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("环绕通知之前");
//调用目标方法
Object proceed = pjp.proceed();
System.out.println("环绕通知之后");
return proceed;
}
//异常拦截通知:如果出现异常就会调用
public void afterException()
{
System.out.println("异常通知");
}
//后置通知:无论是否出现异常都会调用
public void after()
{
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"
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">
<!--配置目标对象-->
<bean name="userServiceTarget" class="com.like.serviceImpl.UserServiceImpl"/>
<!--配置通知对象-->
<bean name="myAdvice" class="com.like.aspect.MyAdvice"/>
<aop:config>
<!--配置切入点
public void com.like.serviceImpl.UserServiceImpl.save() //完整写法
void com.like.serviceImpl.UserServiceImpl.save() //省略public
* com.like.serviceImpl.UserServiceImpl.save() //不对返回值做要求
* com.like.serviceImpl.UserServiceImpl.*() //所有方法,必须是空参
* com.like.serviceImpl.UserServiceImpl.*(..) //所有方法,任意参数,可以没参数
* ..UserServiceImpl.*(..) //当前包及其子包
* com.like.serviceImpl.*ServiceImpl.*(..) //所有方法,ServiceImpl后缀的类
* com.like.serviceImpl.*ServiceImpl.*(int) //指定int类型
* com.like.serviceImpl.*ServiceImpl.*(*) //任意类型,但是必须有参数
* com.like.serviceImpl..*ServiceImpl.*(..) //所有方法,ServiceImpl后缀的类还有它的子包
-->
<aop:pointcut id="pc" expression="execution( * com.like.serviceImpl.*ServiceImpl.*(..))"/>
<!--配置切面, id是切面的唯一标识.ref是通知类的引用-->
<aop:aspect id="myAdvicexxxx" ref="myAdvice">
<!--指定名为before方法作为前置通知-->
<aop:before method="before" pointcut-ref="pc"/> //这里是共用一个切入点了,如果使用ponitcut属性可以单独制定切入点
<!--指定名为afterRunning方法作为后置通知-->
<aop:after-returning method="afterRunning" pointcut-ref="pc"/>
<!--指定名为around方法作为环绕通知-->
<aop:around method="around" pointcut-ref="pc"/>
<!--指定名为afterException方法作为异常通知-->
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<!--指定名为after方法作为最终通知(有异常也通知)-->
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
~~~
调用:
~~~
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userServiceTarget"); //如果符合要求,获取到的就是代理对象.是无法获取被代理对象的
System.out.println(userService);
~~~
## 通用化切入点表达式
所有切面都能使用. 但是必须在所有切面之前.
~~~
<aop:config>
<aop:pointcut id="advice" expression="execution(* com.like.service.impl.*ServiceImpl.*(..))"/>
<aop:aspect ref="logger">
<aop:around method="around" pointcut-ref="advice"/>
</aop:aspect>
</aop:config>
~~~
## 单个切面使用
~~~
<aop:config>
<aop:aspect ref="logger">
<aop:pointcut id="ad1" expression="execution(* com.like.service.impl.*ServiceImpl.*(..))"/>
<aop:around method="around" pointcut-ref="ad1"/>
</aop:aspect>
</aop:config>
~~~
## 单个方法切入点表达式
~~~
<aop:config>
<aop:aspect ref="logger">
<aop:around method="around" pointcut="execution(* com.like.service.impl.*ServiceImpl.*(..))"/>
</aop:aspect>
</aop:config>
~~~
## 注解方式
~~~
<?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">
<!--配置目标对象-->
<bean id="userServiceTarget" class="com.like.serviceImpl.UserServiceImpl"/>
<!--配置将通知织入目标对象-->
<bean id="myAdvice" class="com.like.aspect.MyAdvice"/>
<!--开启使用注解完成织入-->
<aop:aspectj-autoproxy/>
</beans>
~~~
~~~
package com.like.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
//用该注解表示是通知类
@Aspect
public class MyAdvice
{
@Pointcut("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void pc(){}
//指定该方法是前置通知,并指定切入点
@Before("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void before()
{
System.out.println("前置通知");
}
//后置通知:如果出现异常不会调用
@AfterReturning("MyAdvice.pc()") //这是简写方法,这样讲就不用为每个通知都指定范围了
public void afterRunning()
{
System.out.println("后置通知,异常不调用");
}
//环绕通知:在目标方法之前和之后都调用
@Around("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("环绕通知之前");
//调用目标方法
Object proceed = pjp.proceed();
System.out.println("环绕通知之后");
return proceed;
}
//异常拦截通知:如果出现异常就会调用
@AfterThrowing("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void afterException()
{
System.out.println("异常通知");
}
//最终通知:无论是否出现异常都会调用
@After("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void after()
{
System.out.println("后置通知,异常调用");
}
}
~~~
## 注意
后置通知和一场通知最终只能执行一个.
- Maven
- 概述
- 常用命令
- 生命周期
- scope详解
- maven概念模型图
- IDEA创建maven工程
- 创建maven web项目
- 冲突解决
- pom文件标签详解
- maven工程拆分与聚合的思想
- 父子工程的创建
- 工程和模块的关系以及集成和依赖的概念
- 父子工程添加依赖
- 父子工程的三种启动方式
- Struts2
- 执行流程
- 配置
- action的使用
- 获取Servlet的API
- result标签的视图配置
- struts2属性封装
- struts2模型封装
- OGNL
- 值栈(ValueStack)
- 值栈context区存数据
- 值栈root区
- struts2对el的增强
- #,%,$符号使用
- 值栈扩展
- 拦截器
- 自定义拦截器
- 方法拦截器
- 注解方式
- Hibernate
- 配置
- 简单crud
- 持久化类编写规范
- OID
- 持久化类三种状态
- 一级缓存
- 查询
- session与当前线程绑定
- hibernate一对多配置
- 冗余SQL语句的原因
- hibernate多对多配置
- 级联操作
- 对象导航查询
- JPA
- JPA单表CRUD
- JPA多种查询
- JPA一对多关系映射
- JPA一对多操作
- JPA多对多关系映射
- JPA多对多操作
- QBC查询
- 离线条件查询(DetachedCriteria)
- SpringMVC
- 环境搭建
- 常用注解
- 请求参数绑定
- 绑定基本类型和字符串
- 绑定实体类型
- 解决中文乱码
- 绑定集合类型
- 自定义类型转换器
- 获取Servlet的API
- 响应字符串
- 响应void
- 响应ModelAndView
- 响应forward和redirect
- 响应过滤静态资源
- 响应json
- 文件上传基础
- SpringMVC上传文件
- 跨服务器文件上传
- 拦截器
- SpringMVC异常
- ControllerAdvice
- SpringMVC默认处理方式
- 概述
- @ExceptionHandler
- 消息转换器
- SpringMVC跨域
- Spring
- 概述
- IoC快速入门
- ApplicationContext三个常用实现类
- beanFactory和ApplicationContext区别
- bean创建三种方式
- POJO和Javabean的区别
- bean作用范围
- bean对象生命周期
- spring的依赖注入
- DI的属性注入方式
- 常用注解
- Spring新注解
- Spring整合连接池
- Spring的IOC注解配置
- Spring完全使用注解
- Spring整合junit
- AOP
- AOP配置
- JDBCTemplate
- JDBCTemplate在IOC中使用
- JDBCTemplate的CRUD
- JDBCTemplate在dao中使用
- 声明式事务
- spring事务API
- 事务XML配置
- 事务注解配置
- 全注解事务
- Spring编程式事务
- 整合SSH(XML版本)
- 整合SSH(半XML半注解)
- Spring5新特性
- MyBatis
- 概述
- 用maven创建MyBatis
- 将数据库配置单独文件
- typeAliases标签
- MyBatis的CRUD
- MyBatis实现Dao层开发
- 使用dao和代理类的区别
- MyBatis连接池
- MyBatis事务
- MyBatis动态SQL
- 多表操作
- 多表一对一
- 多表一对多
- 多表多对多
- JNDI
- 延迟加载和立即加载
- 延迟加载
- 一级缓存
- 二级缓存
- MyBatis注解
- MyBatis注解CRUD
- 注解实体类属性和字段对应关系
- MyBatis注解一对一和一对多
- MyBatis注解二级缓存
- SSM整合
- 搭建环境
- SpringBoot
- SpringBoot核心功能
- 快速入门
- SpringBoot配置文件
- yml配置文件语法
- 配置文件与配置类的属性映射方式
- 端口和映射路径
- 日志级别
- 访问静态资源
- SpringBoot注入方式一
- SpringBoot注入方式二
- 拦截器
- HikariCP连接池
- SpringBoot集成MyBatis
- 通用mapper
- SpringBoot事务
- SpringBoot集成Junit
- SpringBoot集成DataJPA
- SpringBoot集成Redis
- 使用SpringBoot提供的测试启动类
- 使用MockMvc
- SpringCloud
- RestTemplate
- Eureka概述
- Eureka快速入门
- Eureka集群
- Eureka客户端
- Eureka失效剔除和自我保护
- 负载均衡Ribbon
- Hystrix
- Hystrix服务降级
- Hystrix服务熔断
- Feign
- Feign的熔断机制
- Feign的请求压缩和日志级别
- Zuul网关
- Zuul快速入门
- Zuul路由规则
- Zuul过滤器
- Zuul自定义过滤器
- Zuul负载均衡和熔断
- Zuul高可用
- Zuul网关缓存
- SpringSecurity
- 快速入门
- SpringSecurity使用数据库认证