面向切片编程
1. 谁能解释一下java面向切面编程的思想 以及具体的使用方式
面向切面编程(AOP),就是关注程序运行的过程,切面就是要把方法切开,分别执行前,执行中,执行后(可能更细化)等多个步骤,分别针对这三个阶段进行处理。以获得逻辑过程中各部分之间低耦合性的隔离效果。
具体使用场景:
事务管理:我们在操作数据库的时候需要在操作前打开事务,结束后提交事务(或回滚事务),按往常的编码方式,我们会在每个方法前、后都添加一些事务操作的重复的代码,使得每个类都与事务操作相耦合;而使用了AOP,代码上看上去就是直接操作的数据库,而我们通过某种机制,可让代码在你不察觉的情况下进行了事务开启和提交(或回滚),事实上Spring就提供了这种事务机制。
差不多的场景还有日志的记录
2. spring中的aop 是怎么面向切面编程的
Spring面向切面编程(AOP)
1 spring容器中bean特性
Spring容器的javabean对象默认是单例的。
通过在xml文件中,配置可以使用某些对象为多列。
Spring容器中的javabean对象默认是立即加载(立即实例化:spring加载完成,立即创建对象)
scope:属性
singleton:默认值为单例,默认也是立即加载,在加载完成spring容器的时候,bean对象已经创建完成
prototype:多例的,默认懒加载,spring容器加载完成的时候,不会创建bean的对象,只有从容器获得bean对象的时候,才进行bean对象的实例化
request: 将创建的javabean对象,封装到request范围
session:将创建的javabean对象,封装到session范围
Spring容器bean的对象生命周期:
Bean对象的创建一直到销毁为bean的生命周期。
生命周期的开始:
如果为单例,由加载完spring容器开始
如果为多例,由从容器获得bean对象开始
实例化
初始化
服务
销毁(单例:关闭容器的时候,多例由jvm自动回收)
2 spring的AOP面向切面编程
2.1 模拟银行转账业务
需求:实现银行的转账功能,在转账的时候需要完成
1 身份认证(登陆)
2 权限的验证
3 转账实现
4 历史交易记录,
分析:1,2,4三个功能对于银行的业务,属于公共的功能(共性的功能)
在功能实现的时候,需要将1,2,4抽取出来,单独实现,
做到了将共性的功能和核心的业务功能进行了分离
通过动态代理实现:共性的功能和核心业务功能的合并,产生核心业务对象的
在代码实现的时候,进行了功能实现的分离:
代码开发的进行分离,程序在运行的时候进行合并。
2.2 springAOP的思想
在系统开发中,将系统的共性的公共的功能独立实现,在程序运行的过程中,将共性功能和核心的业务功能,进行整合。
好处:
1 完成共性功能和核心业务功能的解耦合
2 提供共性功能的复用性。
2.3springAOP的概念
Aspect切面:封装共性功能的(增强功能的)类
Advice通过:切面类中封装的增强功能的方法。
PointCut:切入点,是一个集合的概念,该集合的表达使用一个正则表达式表达
所有核心业务对象的所有方法的前后(事务处理AOP典型的应用)
JoinPoint:连接点,程序中需要加入advice的地方,而且正在执行的ponitCut
织入(Weaving):将aspect和核心业务对象,进行整合的过程。
3 springAOP的实现
3.1通过特定接口实现
Aop通知的类型:
Before:前置通知
After:后置通知
Around:环绕通知
Throwing:异常通知
需求:实现在业务对象中的方法执行的时候,记录日志功能
3.1.1前置通知
packageorg.guangsoft.utils;
importjava.lang.reflect.Method;
importjava.util.Arrays;
importjava.util.Date;
importorg.springframework.aop.MethodBeforeAdvice;
/****
*前置增强:
*MethodBeforeAdvice接口表示重写的方法为前置advice
****/
{
@Override
publicvoidbefore(Methodmethod,
Object[]args,Objectobj)
throwsThrowable
{
System.out.println(method);
System.out.println(Arrays.toString(args));
System.out.println(obj);
System.out.println("BeforeLog-------------"+newDate());
}
}
AOP配置:
<?xmlversion="1.0"encoding="UTF-8"?>
<!--到入xml文件的约束-->
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
<!--实例化BeforeLog对象-->
<beanid="bf"class="org.guangsoft.utils.BeforeLog"></bean>
<!--实例化service对象-->
<beanid="us"class="org.guangsoft.service.impl.UsersServiceImpl"/>
<!--进行aop的配置,产生代理对象-->
<aop:config>
<!--声明切入点-->
<aop:pointcutexpression="execution(*org.guansoft.service.impl.*.*(..))"
id="pc"/>
<!--织入将通知和切入点进行合并(切面+核心业务对象)-->
<aop:advisoradvice-ref="bf"pointcut-ref="pc"/>
</aop:config>
</beans>
3.1.2后置通知
对业务对象的方法进行后增强。
packageorg.guangsoft.utils;
importjava.lang.reflect.Method;
importjava.util.Date;
importorg.springframework.aop.AfterReturningAdvice;
/***
*后置通知
****/
{
@Override
publicvoidafterReturning(Objectobj1,//obj1接收目标方法的返回值
Methodmethod,
Object[]args,
Objectobj2)throwsThrowable
{
//System.out.println(obj1+"----------------------"+obj2);
System.out.println("AfterLog-------------------"+newDate());
}
}
AOP配置:
<?xmlversion="1.0"encoding="UTF-8"?>
<!--到入xml文件的约束-->
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
<!--实例化BeforeLog对象-->
<beanid="bf"class="org.guangsoft.utils.BeforeLog"></bean>
<beanid="af"class="org.guangsoft.utils.AfterLog"></bean>
<!--实例化service对象-->
<beanid="us"class="org.guangsoft.service.impl.UsersServiceImpl"/>
<!--进行aop的配置,产生代理对象-->
<aop:config>
<!--声明切入点-->
<aop:pointcutexpression="execution(*org.guangsoft.service.impl.*.*(..))"
id="pc"/>
<!--织入将通知和切入点进行合并(切面+核心业务对象)-->
<aop:advisoradvice-ref="bf"pointcut-ref="pc"/>
<aop:advisoradvice-ref="af"pointcut-ref="pc"/>
</aop:config>
</beans>
3.1.3环绕通知
packageorg.guangsoft.utils;
importjava.lang.reflect.Method;
importjava.util.Arrays;
importjava.util.Date;
importorg.aopalliance.intercept.MethodInterceptor;
importorg.aopalliance.intercept.MethodInvocation;
/***
*环绕通知
****/
{
/**
*MethodInvocation中封装了目标对象,调用的方法,方法需要的参数
****/
@Override
publicObjectinvoke(MethodInvocationmi)throwsThrowable
{
Methodmethod=mi.getMethod();
Object[]args=mi.getArguments();
Objectobj=mi.getThis();
System.out.println(method);
System.out.println(Arrays.toString(args));
System.out.println(obj);
System.out.println("around------before--------"+newDate());
Objectrv=method.invoke(obj,args);//调用目标对象的方法,放行
System.out.println("around------after--------"+newDate());
returnrv;
}
}
AOP配置:同上
3.1.4 异常通知
packageorg.guangsoft.utils;
importjava.util.Date;
importorg.springframework.aop.ThrowsAdvice;
/****
*异常通知
***/
{
/***
*该类中的方法参考AfterReturningAdvice写
*该参数是用来接收异常信息的
****/
publicvoidafterThrowing(Throwableex)throwsThrowable
{
//System.out.println(obj1+"----------------------"+obj2);
System.out.println("ExceptionLog-----------"+ex.getMessage()
+"--------"+newDate());
}
}
Pointcut:核心业务对象
Advice:通知
3. 什么是面向切面编程AOP
面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。
但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。
这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。
AOP在编程历史上可以说是里程碑式的,对OOP编程是一种十分有益的补充。
4. 什么是面向切面编程
“面向切面编程”。只有当你真正的理解OOP之后,才可以理解AOP(面向切面编程)的思想。
这个思想,不是一两句就能将的明白的。用个生活中的例子:
人的手可以写字,并且可以用很多中笔来写字。例如,钢笔、铅笔、毛笔等等。(这里抽象的说)如果我们要用到人的手写字的时候,就必须提供给手很多中笔,可是每种笔的类型有各自不同,我们说笔有很多不同的属性的功能。如果才能让我们的手拿到任何一种笔都可以写字呢,我们可以这样做。将钢笔、铅笔、毛笔等等笔定义一种公共的“笔”的类型,让我们的手在使用笔的时候,只需要知道要使用一个笔来写字,而不需要关心使用什么笔来写。而决定给这只手用的笔的类型,就是你的事情了。
抽象成简单的代码:
interface Pen{}
class GangBi implements Pen{}
class MaoBi implements Pen{}
class QianBi implements Pen{}
class Human{
void usePen(Pen pen){}
}
这个概念超级抽象。不过,学习Spring框架可以快速的来理解这个概念。
5. 面向切面编程的简介
Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。比如我们最常见的就是日志记录了,举个例子,我们现在提供一个服务查询学生信息的,但是我们希望记录有谁进行了这个查询。如果按照传统的OOP的实现的话,那我们实现了一个查询学生信息的服务接口(StudentInfoService)和其实现类(StudentInfoServiceImpl.java),同时为了要进行记录的话,那我们在实现类(StudentInfoServiceImpl.java)中要添加其实现记录的过程。这样的话,假如我们要实现的服务有多个呢?那就要在每个实现的类都添加这些记录过程。这样做的话就会有点繁琐,而且每个实现类都与记录服务日志的行为紧耦合,违反了面向对象的规则。那么怎样才能把记录服务的行为与业务处理过程中分离出来呢?看起来好像就是查询学生的服务自己在进行,但却是背后日志记录对这些行为进行记录,并且查询学生的服务不知道存在这些记录过程,这就是我们要讨论AOP的目的所在。AOP的编程,好像就是把我们在某个方面的功能提出来与一批对象进行隔离,这样与一批对象之间降低了耦合性,可以就某个功能进行编程。

6. 面向切面编程和面向接口编程的区别
谈谈自己的理解吧:
面向切面编程:
手段:分离业务的主逻辑和次逻辑的一种思想。
目的:解决的是逻辑分离问题(主逻辑和次逻辑分开,其实主要是分离业务逻辑和非业务逻辑分开)。
案例:我们开发项目的时候基本都要去连接数据库操作数据等,但是都会涉及到事务的提交,这时我们就用到了面向切面编程,我们在业务层只写自己的业务逻辑,提交事务这一块统一的动作我们就浓缩到了一块儿统一处理,形象一点比喻就是我们做什么事之前都以一个准备动作或结束动作的时候就把它统一起来,只关注我们要完成的事,这些准备动作统一完成!
类似的面向切面编程案例还有:系统日志的记录、请求的拦截等
面向接口编程:
手段:通过接口规约对象的属性和方法,是面向对象一部分。
目的:统一标准问题,让大家不至于各行其事而对代码的可读性造成影响(公用部分行为)。
案例:其实这个比较好解释,就是有一件事,需要大家去完成,但是给你规定了完成的方式,你只能怎么去做,这时我们当中任何一个人都能去完成这件事,只不过因人而异会有效率和风格的差异,但是都是按照事先的规定来的!比如:让你去给数据库添加一行数据返回受影响的行数,这里大家都去实现接口写SQL,中间可能会有差异,但是最后都得返回一个int类型的受影响行数回来
大体意思就是说:接口给我们规定了完成一个任务的标准,但是具体过程不限制,任何人都能通过遵循的规定去完成这件事!这样扩展性就很强!
个人水平有限,如果不满意请参考:网页链接
7. 什么是AOP面向切面编程
aspect
oriented
programming(面向切面编程),可以
通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一
添加功能的一种技术。
8. spring框架的面向切面编程如何理解
Spring提供了对AOP技术的良好封装,AOP称为面向切面编程,就是系统中有很多各不相干的类的方法,在这些众多的方法中要加入某种系统功能代码,例如:加入日志、权限判断、异常处理等,这种应用成为AOP。
实现AOP功能采用的是代理技术,客户端程序不再调用目标,而调用代理类,代理类与目标类对外具有相同的方法声明,有两种方式可以实现相同的方法声明,一是实现相同的接口,而是作为目标的子类在JDK中采用Proxy类产生动态代理的方式为某个接口生成实现类,如果要为某类个生成子类,则可以用CGLIB。
在生成的代理类的方法中加入系统功能和调用目标类的相应方法,系统功能的代理以Advice对象进行提供,显然要创建出代理对象,至少需要目标类和Advice类。
Sping提供了这种支持,只需要在Sping配置文件中配置这两个元素即可实现代理和Aop功能,
例如:
<bean id = "proxy" type = "org.spring.framework.aop.ProxyBeanFacory">
<property name = "target" ref = ""></property>
<property name = "advisor" ref = ""></property>
</bean>
9. 什么是aop
AOP为Aspect Oriented Programming的缩写,是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
AOP的出现弥补了OOP的这点不足,AOP 是一个概念,一个规范,本身并没有设定具体语言的实现,AOP是基于动态代理模式。AOP是方法级别的,要测试的方法不能为static修饰,因为接口中不能存在静态方法,编译就会报错。
AOP可以分离业务代码和关注点代码(重复代码),在执行业务代码时,动态的注入关注点代码。切面就是关注点代码形成的类。Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。

(9)面向切片编程扩展阅读
AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ。而动态代理则以Spring AOP为代表,静态代理是编译期实现,动态代理是运行期实现,可想而知前者拥有更好的性能。
静态代理是编译阶段生成AOP代理类,也就是说生成的字节码就织入了增强后的AOP对象;动态代理则不会修改字节码,而是在内存中临时生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
10. 什么是AOP编程
面向切面编程(也叫面向方面):Aspect
Oriented
Programming(AOP),是目前软件开发中的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP是OOP的延续,是(Aspect
Oriented
Programming)的缩写,意思是面向切面(方面)编程。
可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。
