Spring——Ioc和AOP
这两天学习了Spring框架的主要特性,包括Bean、DI、IoC、AOP、jdbc事务等,写篇博客来做个总结,主要介绍IoC和AOP
Ioc
IoC(Inversion of Control)
Ioc(控制反转)也称为DI(依赖注入),它是一个过程,对象仅通过构造函数参数、工厂方法的参数或从工厂方法构造或返回对象实例后在其上设置的属性来定义其依赖项(即与之一起工作的其他对象); 或从工厂方法构造或返回对象实例后在其上设置的属性。然后,容器在创建bean时注入这些依赖项。这个过程基本上是bean本身的逆过程(因此称为控制反转),通过直接构造类或服务定位器模式等机制来控制其依赖项的实例化或位置。
代码测试
业务代码
(1)、Person类
1 | package net.zzqd.spring.pojo; |
(2)、Car类
1 |
|
(3)、工厂方法
1 | package net.zzqd.spring.Factory; |
配置代码
(1)、依赖注入
1 | <?xml version="1.0" encoding="UTF-8"?> |
(2)、控制反转
1 | <?xml version="1.0" encoding="UTF-8"?> |
测试代码
(1)、依赖注入
1 | package net.zzqd.spring.pojo; |
(二)、控制反转
1 | package net.zzqd.spring.pojo; |
AOP
AOP(Aspect Oriented Programming)
AOP为Aspect Oriented Programming的缩写、意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合降低,提高程序的可重用性,同时提高了开发的效率
AOP思想:横向重复、纵向抽取
底层实现
Spring的AOP底层用到了两种代理机制:
JDK的动态代理:针对实现了接口的类产生代理。
Cglib的动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术,生成当前类的子类对象。
AOP开发相关术语
- Joinpoint(连接点):所谓连接点是指那些被拦截的点,在spring中,这些点指的是方法,因为spring只支持方法类型的连接点(可以被切入的点)
- Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义,(已知被切入的点)
- Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能)
- Introduction(引介):引介是一种特殊的通知在不改类代码的前提下,Introduction可以在运行期为类动态添加一些方法或Field。
- Aspect(切面):是切入点和通知(引介)的结合
- Targer(目标对象):代理的目标对象
- Proxy(代理):一个类被AOP织入增强后,就产生了一个结果代理类。
- Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用预编译期织入和类装载期织入
代码测试
业务代码:
(1)、service接口代码
1 | package net.zzqd.spring.aop.service; |
(2)、service实现类
1 | package net.zzqd.spring.aop.service; |
配置文件代码
用xml配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 目标对象 -->
<bean name="userService" class="net.zzqd.spring.aop.service.UserServiceImpl"></bean>
<!-- 通知对象 -->
<bean name="transactionAdvice" class="net.zzqd.spring.aop.advice.TransactionAdvice"></bean>
<!-- 将通知对象织入目标对象 -->
<aop:config>
<!-- 选择切入点 -->
<aop:pointcut expression="execution(* net.zzqd.spring.aop.service..*ServiceImpl.*(..))" id="pointcut"/>
<aop:aspect ref="transactionAdvice">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturnning" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/><!--无论是否出现异常都执行-->
<aop:around method="around" pointcut-ref="pointcut"/>
<aop:after-throwing method="afterException" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
使用注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 目标对象 -->
<bean name="userService" class="net.zzqd.spring.aop.service.UserServiceImpl"></bean>
<!-- 通知对象 -->
<bean name="transactionAdvice" class="net.zzqd.spring.aop.advice.TransactionAdvice"></bean>
<!-- 开启织入注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>aop代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54package net.zzqd.spring.aop.advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* @author zzq
* @version 创建时间:2019年5月30日 下午6:28:06
*
*/
@Aspect
public class TransactionAdvice {
//前置通知:在目标方法之前调用
//后置通知:(如果出现异常就不调用)在目标方法之后调用
//后置通知:(无论是否出现都会调用)在目标方法之后调用
//环绕通知:在目标执行方法之前之后调用
//异常通知:出项异常则调用
@Pointcut("execution(* net.zzqd.spring.aop.service..*ServiceImpl.*(..))")
public void point() {}
@Before("TransactionAdvice.pointcut()")
public void before()
{
System.out.println("前置通知被执行");
}
@AfterReturning("TransactionAdvice.pointcut()")
public void afterReturnning()
{
System.out.println("后置通知被执行(如果出现异常就不调用)");
}
@After("TransactionAdvice.pointcut()")
public void after()
{
System.out.println("后置通知被执行");
}
@AfterThrowing("TransactionAdvice.pointcut()")
public void afterException()
{
System.out.println("异常通知被执行");
}
@Around("TransactionAdvice.pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable
{
System.out.println("环绕通知前");
Object proceed = point.proceed();//调用目标方法
System.out.println("环绕通知后");
return proceed;
}
}
测试代码
1 | import javax.annotation.Resource; |
我是作者,博客评论系统初始化成功,纪念一下!