浅谈AOP和IOC
笔者也是初识Spring,有什么不对的地方还请斧正!
近来在学习Spring框架,初识框架有点迷惑,所以整理一下目前所学的一些知识吧。
AOP即 Aspect Oriental Program 面向切面编程 ,为什么要先说AOP呢,因为Spring是一个基于AOP和IOC的框架。IOC简单点说就是你以前创建对象都是用new,现在Spring直接承包了,你不用去管如何创建对象了,你直接用就行,就像是去食堂吃饭,厨师大叔们都把菜给你做好了,你只管吃就行了。AOP呢就是一个面向切面的编程,注意,切面这个词很重要,你要理解透了切面的含义对于理解AOP也就没有多大问题了。
通俗点讲AOP的思想就是把功能分成两大部分,一部分是核心的功能,另一部分是周边功能(验证,事务,缓存等),然后这个周边功能叫做切面,他们两大部分分别独立的进行开发,你开发你的,我开发我的,到最后将这两部分进行低耦合的结合,这种思想称为切面编程。这两部分之间耦合度很低,他们分别独立开发互不影响,这是最好的开发模式。在Spring中是通过注解或者是配置文件来实现两部分结合的。这个过程很抽象,说白了框架其实就是一种高度集成的抽象。接下来我们举一个例子来方便理解一下。
首先我要有一个业务类:
public class ProductService {
public void doSomeService(){
System.out.println("我这里是业务类");
}
}
然后我还要有一个切面类姑且就用来管理日志吧:
public class LoggerAspect {
public void log(){
System.out.println("我是切面类,我用来管理日志");
}
}
再然后就是一个配置文件,这里我就不用注解了,用配置文件的话方便理解:
<!--声明业务对象-->
<bean name="s" class="cn.spring.ProductService">
</bean>
<!--声明日志切面-->
<bean id="loggerAspect" class="cn.spring.LoggerAspect"/>
<aop:config>
<!--切点-->
<!--设置好切点 当触发这个切点的时候就会调用辅助功能(切面)中的方法 触发机制就是当访问了这个类中的任意一个方法的时候-->
<aop:pointcut id="loggerCutpoint" expression="execution(* cn.spring.ProductService.*(..)) "/>
<!--切面 log叫通知 some..叫方法-->
<aop:aspect id="logAspect" ref="loggerAspect">
<aop:after pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>
</aop:config>
最后就是测试类,得出结论之后我会一一进行讲解的:
public class TestSpring {
public static void main(String[] args ){
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"cn/spring/applicationContext.xml"});
ProductService s = (ProductService)context.getBean("s");
s.doSomeService();
}
}
输出结果:
接下来我对整个运行过程梳理一遍,一开始先运行的肯定是测试类,在测试类中取出配置文件中的信息,然后通过Spring新建一个业务类的对象,ProductService s = (ProductService)context.getBean("s");
就是这一句创建了一个业务类的对象,然后调用业务类中的方法,在调用业务类中的方法的时候相当于在这里有一个断点,先不急着去调用方法,需要根据配置文件中描述的进行操作。那么配置文件中说的是什么呢?在配置文件中一上来先声明了两个对象<bean name="s" class="cn.spring.ProductService">
,还有<bean id="loggerAspect" class="cn.spring.LoggerAspect"/>
,然后再进行配置,先声明切入点,切入点这个概念很重要,有切入点那肯定有与之对应的,在这里我们就叫他切面,<aop:pointcut id="loggerCutpoint" expression="execution(* cn.spring.ProductService.*(..)) "/>
,这是设置到的切点,大体意思就是有一个id用来标记这个切入点,然后后面相当于是一个触发机制,**意思就是说执行了业务类中的任意一个方法的时候我就会触发切面操作。**那么切面都做了哪些事情呢?首先它定义了一个id用来标记他,然后他就会ref到切面类中,所谓切面操作其实就是调用了一个类的普通方法而已。。。
<!--切面 log叫通知 some..叫方法-->
<aop:aspect id="logAspect" ref="loggerAspect">
<aop:after pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>
这个通知是有很多类型的,你可以改成想这样<aop:before pointcut-ref="loggerCutpoint" method="log"/>
,同学们看出去别来了吗,其实就是一个谁先调用的问题,这个如果用注解的话也是有相应的注解的,如@Before(value = "execution(* cn.spring.ProductService.*(..))")
。
一共有五种类型:
-
Before——在方法调用之前调用通知
-
After——在方法完成之后调用通知,无论方法执行成功与否
-
After-returning——在方法执行成功之后调用通知
-
After-throwing——在方法抛出异常后进行通知
-
Around——通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
最后一个我的理解就是这个方法可以被包裹进去,在通知里面也可以调用方法。
参考文献
https://www.cnblogs.com/mxck/p/7027912.html?utm_source=itdadao&utm_medium=referral
https://blog.youkuaiyun.com/yanquan345/article/details/19760027?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control
https://how2j.cn/k/spring/spring-injection/88.html#step215