回顾:
创建对象的注解: @Component,@Controller,@Service,@Repository
依赖注入的注解: @Autowired,@Value
生命周期的注解: @Scope
纯注解编程:@Bean
单元测试的注解:
- 动态代理
动态代理: 在不改变类源代码的前提下对方法进行增强.
1.1 静态代理
1.2 基于接口的动态代理
生成的动态代理对象是接口的实现类( 1. 增强,2调用被代理对象的方法)
/**
* 基于接口的动态代理:
* 创建接口的实现类
* 使用JDK提供的Proxy工具类创建
*/
public class JdkProxyTest {
public static void main(String[] args) {
//1.创建了被代理对象
AccountService as = new AccountServiceImpl();
//2.创建动态代理对象
/**
* 参数:
* 1.类加载器
* 2.接口的字节码数组 : as.getClass().getInterfaces()
* 3.增强的代码块(invocationHandler)
*/
AccountService proxy = (AccountService)Proxy.newProxyInstance(JdkProxyTest.class.getClassLoader(), new Class[]{AccountService.class}, new InvocationHandler() {
/**
* 增强的业务逻辑
* proxy : 代理对象的引用
* method : 当前执行的方法对象
* args : 当前执行方法的所有参数
* invoke方法中,代码的执行步骤:
* 1.增强
* 2.调用被代理对象的方法
* 3.返回值: 一般而言和被代理对象方法的返回值一模一样
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("1.进入被代理对象方法之前打印日志");
Object rtValue = null;
try{
//执行被代理对象的方法
rtValue = method.invoke(as,args);//1.方法是所属对象,2.方法的所有参数
System.out.println("2.调用被代理对象方法得到返回值之后打印日志");
}catch (Exception e) {
e.printStackTrace();
System.out.println("3.抛出异常打印日志");
}finally {
System.out.println("4.最终代码块打印日志");
}
return rtValue;
}
});
//3.调用动态代理对象的save方法
proxy.update("123");
}
}
1.3 基于子类的动态代理
应用场景: 延迟加载
动态代理对象: 是被代理对象的子类
工具类 : cglib
/**
* 基于子类的动态代理:
* 创建被代理对象的子类
* 使用cglib创建
*/
public class CglibProxyTest {
public static void main(String[] args) {
//1.创建了被代理对象
AccountServiceImpl as = new AccountServiceImpl();
//2.创建动态代理对象
/**
* 使用cglib创建动态代理对象 :Enhancer.create()
* 参数:
* 1.被代理对象(父类)的字节码对象
* 2.增强的业务逻辑(jdk的动态代理的invocationHandler相似)
*/
AccountServiceImpl proxy = (AccountServiceImpl)Enhancer.create(AccountServiceImpl.class, new MethodInterceptor() {
/**
* intercept : 增强的业务逻辑
* proxy : 动态代理对象的引用(不用)
* method : 当前执行的方法对象
* args : 当前执行的方法对象的所有参数
* methodProxy: 当前执行的方法对象的动态代理对象(不用)
*
* 方法执行的顺序
* 1.增强
* 2.调用被代理对象(父类)的方法
* 3.返回值
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("1.进入被代理对象方法之前打印日志");
Object rtValue = null;
try{
//执行被代理对象的方法
rtValue = method.invoke(as,args);//1.方法是所属对象,2.方法的所有参数
System.out.println("2.调用被代理对象方法得到返回值之后打印日志");
}catch (Exception e) {
e.printStackTrace();
System.out.println("3.抛出异常打印日志");
}finally {
System.out.println("4.最终代码块打印日志");
}
return rtValue;
}
});
//3.调用动态代理对象的save方法
proxy.findById("123");
}
}
-
转账案例
2.1 ThreadLocal
ThreadLocal:将数据绑定到当前线程
2.2 事务控制
- AOP相关概念
3.1 Aop的概念
3.2 专业术语
- AOP相关概念
连接点(Join point):
被代理对象中的所有方法
切入点(Point cut):
被代理对象中所有被增强的方法
增强/通知(Advice):
增强的业务逻辑
织入(Weaving)
动作:动态代理
目标对象(Target)
被代理对象
切面(Aspect)
切入点和通知之间的关联关系
3.3 通知的类型
前置通知 : 调用被代理对象方法之前执行的增强内容
后置通知 : 调用被代理对象方法得到返回值之后执行的增强内容
异常通知 : 抛出异常的时候执行的增强内容
最终通知 : 在finally代码块中执行的增强内容
环绕通知 :
- 基于XML的AOP配置(重点)
案例 : 对账户service进行日志部分的增强
操作步骤:
1. 创建工程导入坐标
2. 搭建工程基本结构
3. 完成IOC的配置
4. 编写增强业务逻辑类(切面类),编写增强业务逻辑的方法
5. 配制AOP
<aop:config>
//切入点
<aop:ponitcut id=”唯一标志” expression=”execution(* cn.itcast.service..*.*(..))”></ aop:ponitcut >
//切面
<aop:aspect ref=”切面类的唯一标识”>
//配置通知类型
<aop:before method=”切面类的方法名” pointcut-ref=”切入点的id”></ aop:before >
<aop:after-returning method=”切面类的方法名” pointcut-ref=”切入点的id”></ aop: :after-returning >
<aop: after-throwing method=”切面类的方法名” pointcut-ref=”切入点的id”></ aop: after-throwing >
<aop:after method=”切面类的方法名” pointcut-ref=”切入点的id”></ aop:after>
<aop:around method=”切面类的方法名” pointcut-ref=”切入点的id”></ aop: around >
</ aop:aspect >
</aop:config>
4.1 创建工程导入坐标
<dependencies>
<!--ioc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--aop坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--aspectJ : 表达式语言的jar包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
</dependencies>
4.2 搭建工程基本结构
4.3 完成IOC的配置
4.4 编写切面类
切面类:所有增强的业务逻辑方法
4.5 配制AOP
将切面类交给spring容器管理
声明AOP配置
配置切入点
配置切面
4.6 切入点表达式
4.7 环绕通知
配置:
5. 基于注解结合xml的AOP配置(重点)
注解:
Ioc注解
Aop配置
5.1 开启对注解的支持
包扫描和开启对AOP注解的支持
5.2 注解配置AOP
注解需要配置到切面类上
5.3 声明切面类
@Aspect
5.4 配置通知类型
@Before:前置通知
@AfterReturni
@AfterThrowin
@After:最终通知
@Around:环绕通知
5.5 定义公共的切入点
@PonitCut
6. 基于纯注解的AOP配置(了解)
7. 基于AOP的转账案例(作业)
面试问题:
AOP: