本文目录
- spring aop 可以实现什么
- spring的aop怎样实现
- Spring AOP 一般用在什么场景中
- spring AOP的原理,以及什么是AOP
- Spring的AOP有什么作用
- spring配置aop的方式有哪些
- spring的aop是什么意思
- spring aop 有什么用途
- 如何理解Spring的AOP
- 有人能通俗介绍下SPRING的AOP吗
spring aop 可以实现什么
AOP技术利用一种称为“横切”的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。
实现原理
前面在学习代理模式的时候,了解到代理模式分为动态代理和静态代理。现在我们就以代理模式为基础先实现我们自己的AOP框架,再来研究Spring的AOP的实现原理。
先以静态代理实现,静态代理关键是在代理对象和目标对象实现共同的接口,并且代理对象持有目标对象的引用。
公共接口代码:
1 public interface IHello {
2 /**
3 * 业务方法
4 * @param str
5 */
6 void sayHello(String str);
7 }
目标类代码:
1 public class Hello implements IHello{
2 @Override
3 public void sayHello(String str) {
4 System.out.println(“hello “+str);
5 }
6
7 }
代理类代码,我们给它添加日志记录功能,在方法开始前后执行特定的方法,是不是和AOP特别像呢?
public class ProxyHello implements IHello{
private IHello hello;
public ProxyHello(IHello hello) {
super();
this.hello = hello;
}
@Override
public void sayHello(String str) {
Logger.start();//添加特定的方法
hello.sayHello(str);
Logger.end();
}
}
日志类代码:
1 public class Logger {
2 public static void start(){
3 System.out.println(new Date()+ “ say hello start...“);
4 }
5
6 public static void end(){
7 System.out.println(new Date()+ “ say hello end“);
8 }
9 }
测试代码:
1 public class Test {
2 public static void main(String args) {
3 IHello hello = new ProxyHello(new Hello());//如果我们需要日志功能,则使用代理类
4 //IHello hello = new Hello();//如果我们不需要日志功能则使用目标类
5 hello.sayHello(“明天“);
6 }
7 }
这样我们就实现了一个最简单的AOP,但是这样会存在一个问题:如果我们像Hello这样的类很多,那么,我们是不是要去写很多个HelloProxy这样的类呢。其实也是一种很麻烦的事。在jdk1.3以后,jdk跟我们提供了一个API java.lang.reflect.InvocationHandler的类, 这个类可以让我们在JVM调用某个类的方法时动态的为些方法做些什么事。下面我们就来实现动态代理的实现。
动态代理实现主要是实现InvocationHandler,并且将目标对象注入到代理对象中,利用反射机制来执行目标对象的方法。
接口实现与静态代理相同,代理类代码:
1 public class DynaProxyHello implements InvocationHandler{
2
3 private Object target;//目标对象
4 /**
5 * 通过反射来实例化目标对象
6 * @param object
7 * @return
8 */
9 public Object bind(Object object){
10 this.target = object;
11 return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
12 }
13
14 @Override
15 public Object invoke(Object proxy, Method method, Object args)
16 throws Throwable {
17 Object result = null;
18 Logger.start();//添加额外的方法
19 //通过反射机制来运行目标对象的方法
20 result = method.invoke(this.target, args);
21 Logger.end();
22 return result;
23 }
24
25 }
测试类代码:
1 public class DynaTest {
2 public static void main(String args) {
3 IHello hello = (IHello) new DynaProxyHello().bind(new Hello());//如果我们需要日志功能,则使用代理类
4 //IHello hello = new Hello();//如果我们不需要日志功能则使用目标类
5 hello.sayHello(“明天“);
6 }
7 }
看完上面的代码可能和Spring AOP相比有一个问题,日志类只能在方法前后打印,但是AOP应该是可以在满足条件就可以执行,所有是否可以将DynaPoxyHello对象和日志操作对象(Logger)解耦呢?
看下面代码实现,将将DynaPoxyHello对象和日志操作对象(Logger)解耦:
我们要在被代理对象的方法前面或者后面去加上日志操作代码(或者是其它操作的代码),那么,我们可以抽象出一个接口,这个接口里就只有两个方法:一个是在被代理对象要执行方法之前执行的方法,我们取名为start,第二个方法就是在被代理对象执行方法之后执行的方法,我们取名为end。
Logger的接口:
1 public interface ILogger {
2 void start(Method method);
3 void end(Method method);
4 }
Logger的接口实现:
1 public class DLogger implements ILogger{
2 @Override
3 public void start(Method method) {
4 System.out.println(new Date()+ method.getName() + “ say hello start...“);
5 }
6 @Override
7 public void end(Method method) {
8 System.out.println(new Date()+ method.getName() + “ say hello end“);
9 }
10 }
动态代理类:
1 public class DynaProxyHello1 implements InvocationHandler{
2 //调用对象
3 private Object proxy;
4 //目标对象
5 private Object target;
6
7 public Object bind(Object target,Object proxy){
8 this.target=target;
9 this.proxy=proxy;
10 return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
11 }
12
13
14 @Override
15 public Object invoke(Object proxy, Method method, Object args)
16 throws Throwable {
17 Object result = null;
18 //反射得到操作者的实例
19 Class clazz = this.proxy.getClass();
20 //反射得到操作者的Start方法
21 Method start = clazz.getDeclaredMethod(“start“, new Class{Method.class});
22 //反射执行start方法
23 start.invoke(this.proxy, new Object{this.proxy.getClass()});
24 //执行要处理对象的原本方法
25 method.invoke(this.target, args);
26 //反射得到操作者的end方法
27 Method end = clazz.getDeclaredMethod(“end“, new Class{Method.class});
28 //反射执行end方法
29 end.invoke(this.proxy, new Object{method});
30 return result;
31 }
32
33 }
测试代码:
1 public class DynaTest1 {
2 public static void main(String args) {
3 IHello hello = (IHello) new DynaProxyHello1().bind(new Hello(),new DLogger());//如果我们需要日志功能,则使用代理类
4 //IHello hello = new Hello();//如果我们不需要日志功能则使用目标类
5 hello.sayHello(“明天“);
6 }
7 }
通过上面例子,可以发现通过动态代理和发射技术,已经基本实现了AOP的功能,如果我们只需要在方法执行前打印日志,则可以不实现end()方法,这样就可以控制打印的时机了。如果我们想让指定的方法打印日志,我们只需要在invoke()方法中加一个对method名字的判断,method的名字可以写在xml文件中,这样我们就可以实现以配置文件进行解耦了,这样我们就实现了一个简单的spring aop框架。
spring的aop怎样实现
实现原理
- 1 public interface IHello {2 /**3 * 业务方法4 * @param str5 */6 void sayHello(String str);7 }
- 1 public class Hello implements IHello{2 @Override3 public void sayHello(String str) {4 System.out.println(“hello “+str);5 }6 7 }
- public class ProxyHello implements IHello{
- private IHello hello;
- public ProxyHello(IHello hello) { super(); this.hello = hello;
- }
- @Override public void sayHello(String str) {
- Logger.start();//添加特定的方法 hello.sayHello(str);
- Logger.end();
- }
- }
- 1 public class Logger {2 public static void start(){3 System.out.println(new Date()+ “ say hello start...“);4 }5 6 public static void end(){7 System.out.println(new Date()+ “ say hello end“);8 }9 }
- 1 public class Test {2 public static void main(String args) {3 IHello hello = new ProxyHello(new Hello());//如果我们需要日志功能,则使用代理类4 //IHello hello = new Hello();//如果我们不需要日志功能则使用目标类5 hello.sayHello(“明天“);
- 6 }7 }
- 1 public class DynaProxyHello implements InvocationHandler{ 2 3 private Object target;//目标对象 4 /** 5 * 通过反射来实例化目标对象 6 * @param object 7 * @return 8 */ 9 public Object bind(Object object){10 this.target = object;11 return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);12 }13 14 @Override15 public Object invoke(Object proxy, Method method, Object args)16 throws Throwable {17 Object result = null;18 Logger.start();//添加额外的方法19 //通过反射机制来运行目标对象的方法20 result = method.invoke(this.target, args);21 Logger.end();22 return result;23 }24 25 }
- 1 public class DynaTest {2 public static void main(String args) {3 IHello hello = (IHello) new DynaProxyHello().bind(new Hello());//如果我们需要日志功能,则使用代理类4 //IHello hello = new Hello();//如果我们不需要日志功能则使用目标类5 hello.sayHello(“明天“);6 }7 }
- 1 public interface ILogger {2 void start(Method method);3 void end(Method method);4 }
- 1 public class DLogger implements ILogger{ 2 @Override 3 public void start(Method method) { 4 System.out.println(new Date()+ method.getName() + “ say hello start...“); 5 } 6 @Override 7 public void end(Method method) { 8 System.out.println(new Date()+ method.getName() + “ say hello end“); 9 }10 }
- 1 public class DynaProxyHello1 implements InvocationHandler{ 2 //调用对象 3 private Object proxy; 4 //目标对象 5 private Object target; 6 7 public Object bind(Object target,Object proxy){ 8 this.target=target; 9 this.proxy=proxy;10 return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);11 }12 13 14 @Override15 public Object invoke(Object proxy, Method method, Object args)16 throws Throwable {17 Object result = null;18 //反射得到操作者的实例19 Class clazz = this.proxy.getClass();20 //反射得到操作者的Start方法21 Method start = clazz.getDeclaredMethod(“start“, new Class{Method.class});22 //反射执行start方法23 start.invoke(this.proxy, new Object{this.proxy.getClass()});24 //执行要处理对象的原本方法25 method.invoke(this.target, args);26 //反射得到操作者的end方法27 Method end = clazz.getDeclaredMethod(“end“, new Class{Method.class});28 //反射执行end方法29 end.invoke(this.proxy, new Object{method});30 return result;31 }32 33 }
- 1 public class DynaTest1 {2 public static void main(String args) {3 IHello hello = (IHello) new DynaProxyHello1().bind(new Hello(),new DLogger());//如果我们需要日志功能,则使用代理类4 //IHello hello = new Hello();//如果我们不需要日志功能则使用目标类5 hello.sayHello(“明天“);6 }7 }
前面在学习代理模式的时候,了解到代理模式分为动态代理和静态代理。现在我们就以代理模式为基础先实现我们自己的AOP框架,再来研究Spring的AOP的实现原理。
先以静态代理实现,静态代理关键是在代理对象和目标对象实现共同的接口,并且代理对象持有目标对象的引用。
公共接口代码:
目标类代码:
代理类代码,我们给它添加日志记录功能,在方法开始前后执行特定的方法,是不是和AOP特别像呢?
日志类代码:
测试代码:
这样我们就实现了一个最简单的AOP,但是这样会存在一个问题:如果我们像Hello这样的类很多,那么,我们是不是要去写很多个HelloProxy这样的类呢。其实也是一种很麻烦的事。在jdk1.3以后,jdk跟我们提供了一个API java.lang.reflect.InvocationHandler的类, 这个类可以让我们在JVM调用某个类的方法时动态的为些方法做些什么事。下面我们就来实现动态代理的实现。-springaop
动态代理实现主要是实现InvocationHandler,并且将目标对象注入到代理对象中,利用反射机制来执行目标对象的方法。
接口实现与静态代理相同,代理类代码:
测试类代码:
看完上面的代码可能和Spring AOP相比有一个问题,日志类只能在方法前后打印,但是AOP应该是可以在满足条件就可以执行,所有是否可以将DynaPoxyHello对象和日志操作对象(Logger)解耦呢?-pring
看下面代码实现,将将DynaPoxyHello对象和日志操作对象(Logger)解耦:
我们要在被代理对象的方法前面或者后面去加上日志操作代码(或者是其它操作的代码),那么,我们可以抽象出一个接口,这个接口里就只有两个方法:一个是在被代理对象要执行方法之前执行的方法,我们取名为start,第二个方法就是在被代理对象执行方法之后执行的方法,我们取名为end。-springaop
Logger的接口:
Logger的接口实现:
动态代理类:
测试代码:
通过上面例子,可以发现通过动态代理和发射技术,已经基本实现了AOP的功能,如果我们只需要在方法执行前打印日志,则可以不实现end()方法,这样就可以控制打印的时机了。如果我们想让指定的方法打印日志,我们只需要在invoke()方法中加一个对method名字的判断,method的名字可以写在xml文件中,这样我们就可以实现以配置文件进行解耦了,这样我们就实现了一个简单的spring aop框架。-pring
Spring AOP 一般用在什么场景中
AOP,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。
在不改变原有的逻辑的基础上,增加一些额外的功能。代理也是这个功能,读写分离也能用aop来做。
扩展资料:
AOP/OOP区分
AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。
参考资料来源:百度百科-AOP (面向切面编程)
spring AOP的原理,以及什么是AOP
Spring
AOP是编程框架
AOP是OOP的延续,是Aspect
Oriented
Programming的缩写,意思是面向方面编程。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。
-springaop
Spring的AOP有什么作用
AOP:面向切面,是一种编程思想,OOP的延续。将系统中非核心的业务提取出来,进行单独处理。比如事务、日志和安全等。这个简单来说就是可以在一段程序之前或者之后做一些事。
spring配置aop的方式有哪些
1. 基于xml配置文件的代理配置方式
这种方式在2.0以后很少用了,原因是配置项过多,过于繁琐。但对于理解Spring AOP还是很有帮助的
1.1 定义通知
《bean id=“advice“ class=“yourAdviceImpl“ /》
1.2 定义切点
要定义一个切点,可以选择使用正则表达式方式声明的切点或者AspectJ方式声明的切点。对正则表达式切点,使用Perl5RegexpMethodPointcut或JdkRegexpMethodPointcut(Java
1.4以上版本,不需要Jakarta ORO的支持了);对AspectJ切点,使用AspectJExpressPointcut
《bean id=“pointcut“ class=“org.springframework.aop.support.JdkRegexpMethodPointcut“》
《property name=“pattern“ value=“yourRegularExpression“ /》
《/bean》
《bean id=“pointcut“ class=“org.springframework.aop.aspectj.AspectJExpressionPointcut“》
《property name=“expression“ value=“yourAspectJExpression“ /》
《/bean》
1.3 定义通知者
DefaultPointcutAdvisor是Spring提供的默认通知者,它需要提供通知和切点的引用。
Spring也提供了RegexpMethodPointcutAdvisor和AspectJExpressionPointcutAdvisor来对应两种声明切点的方式,不用再单独定义切点。
《bean id=“advisor“ class=“org.springframework.aop.support.DefaultPointcutAdvisor“》
《property name=“advice“ ref=“advice“ /》
《property name=“pointcut“ ref=“pointcut“ /》
《/bean》
《bean id=“advisor“ class=“org.springframework.aop.support.RegexpMethodPointcutAdvisor“》
《property name=“advice“ ref=“advice“ /》
《property name=“pattern“ value=“yourRegularExpression“ /》
《/bean》
《bean id=“advisor“ class=“org.springframework.aop.aspectj.AspectJExpressionPointcut“》
《property name=“advice“ ref=“advice“ /》
《property name=“expression“ value=“yourAspectjExpression“ /》
《/bean》
1.4 定义ProxyFactoryBean
《bean id=“yourBean“ class=“org.springframework.aop.framework.ProxyFactoryBean》
《property name=“target“ ref=“yourTargetBean“ /》
《property name=“interceptorNames“ value=“advisor“ /》
《property name=“proxyInterfaces“ value=“interfaceClass“ /》
《/bean》
interceptorNames和proxyInterfaces都是数组属性,所以可以声明要使用的一个list,也可以让Spring自动把单个值转化为数组
上面明确定义了要对那个targetBean应用代理生成切面实例。如果不想限制targetBean,可以让Spring为所有匹配切点声明的bean生成切面实例,这样就不用一个个定义ProxyFactoryBean了,只需要定义
《bean class=“org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator“ /》
这是一个BeanPostProcessor,所以Spring会自动识别并在bean的声明周期使用
2 利用2.0以后使用aop标签
《aop:config》
《aop:aspect ref=““》
《aop:pointcut id=“performance“ expression=“execution(* *.perform(..))“ /》
《aop:before method=““ pointcut-ref=“performance“ /》
《aop:before method=““ pointcut=“execution(* *.perform(..))“ /》
《aop:after-returning method=““ pointcut=“execution(* *.perform(..))“ /》
《aop:after-throwing method=““ pointcut=“execution(* *.perform(..))“ /》
《/aop:aspect》
《/aop:config》
3 利用Annotation
3.1 利用@Aspect将一个POJO类声明为一个切面。
3.2 定义切点
@Pointcut(“execution(* *.perform(..))“)
public void performance(){}
通过@Pointcut定义的切点的名字就是它所注解的方法的名字,因此例子中的切点名字是
performance()。这里声明的performance()方法实际圣只是一个标记,为@Pointcut提供附加的点,并不要求有实际意义。
3.3 定义通知
对要执行切面的方法,通过@Before(“performance()“),@AfterReturning
(“performance()“)来定义通知。注意这里提供的切点名称,是performance(),而不是performance
如果对上面的两点不是很理解,也可以省略@Pointcut,而将AspectJ表达式直接定义在@Before等通知中,将上面的两步合为一步,如@Before(“execution(* *.perform(..))“)
3.4 通知Spring创建代理
《aop:aspectj-autoproxy》
这实际上相当于声明了一个AnnotationAwareAspectJAutoProxyCreator,从而根据@Pointcut声明的切点来自动代理匹配的bean实例
4 在Spring中结合进AspectJ
对于超出Spring AOP支持范围的,可以采用这种方式。只需要在Spring中配置AspectJ的Class实例时让Spring能够获得AspectJ类的实例就可以了,比如
《bean class=“a_aspectj_class“ factory-method=“aspectOf“》
《preperty .... /》
《/bean》
-pring
spring的aop是什么意思
在AOP中有几个概念:—方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。—连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。—通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。—切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。所以“”实际上是定义横切逻辑,就是在连接点上做什么,“”则定义了在哪些连接点应用什么。Spring这样做的好处就是可以让多个横切逻辑(即定义的)多次使用,提供可重用性。你后面的两个类实际上就是实现横切逻辑的不同方式,一种需要实现特定接口,一种以POJO+Annotation,在功能上没有太大差别,只是方式不同。
-springaop
spring aop 有什么用途
给你举一个例子,比如一个注册登录系统,当然需要注册的地方有很多,你可能要做一个防止用户名重复注册的模块,这个时候就可以用到Spring的aop了!
在你开发大型的应用时,aop可以发挥很大的功能,对于你模块的耦合,以后的管理,功能升级……!都有很大的帮助
好好的理解一下,争取自己去写一个aop出来!
-pring
如何理解Spring的AOP
Spring的AOP面向切面编程,就是横向的,比如程序运行时都要建日志,相当于SQL的触发器。
Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。-springaop
Spring特点:
1、方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。-pring
2、AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
3、声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
4、方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
6、降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
7、Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。-springaop
有人能通俗介绍下SPRING的AOP吗
想简单通俗的说,额,有难度.AOP主要是针对事物处理来说吧,而且是相对于以前的编程式事物处理的,不用AOP的话,我们得通过硬编码的方式将事物处理写在方法中,有了AOP之后,我们只需要在spring的配置文件中配置一下事物就可以了,这就叫声明式事物处理.一般配置时是通过配置匹配某个格式的方法名,当运行到这种方法的时候spring就会拦截下它来,并给它加上事物的处理了
-pring