浅析spring中的AOP(面向切面编程)
来源:互联网 发布:淘宝erp系统 编辑:程序博客网 时间:2024/05/16 03:36
* 它用来生成代理对象
* 它需要所有的参数
* * 目标对象
* * 增强
* @author cxf
*/
/**
* 1. 创建代理工厂
* 2. 给工厂设置三样东西:
* * 目标对象:setTargetObject(xxx);
* * 前置增强:setBeforeAdvice(该接口的实现)
* * 后置增强:setAfterAdvice(该接口的实现)
* 3. 调用createProxy()得到代理对象
* * 执行代理对象方法时:
* > 执行BeforeAdvice的before()
* > 目标对象的目标方法
* > 执行AfterAdvice的after()
* @author cxf
*
*/
public class ProxyFactory {
private Object targetObject;//目标对象
private BeforeAdvice beforeAdvice;//前置增强
private AfterAdvice afterAdvice;//后置增强
/**
* 用来生成代理对象
* @return
*/
public Object createProxy() {
/*
* 1. 给出三大参数
*/
ClassLoader loader = this.getClass().getClassLoader();
Class[] interfaces = targetObject.getClass().getInterfaces();
InvocationHandler h = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*
* 在调用代理对象的方法时会执行这里的内容
*/
// 执行前置增强
if(beforeAdvice != null) {
beforeAdvice.before();
}
Object result = method.invoke(targetObject, args);//执行目标对象的目标方法
// 执行后置增强
if(afterAdvice != null) {
afterAdvice.after();
}
// 返回目标对象的返回值
return result;
}
};
/*
* 2. 得到代理对象
*/
Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
return proxyObject;
}
public Object getTargetObject() {
return targetObject;
}
public void setTargetObject(Object targetObject) {
this.targetObject = targetObject;
}
public BeforeAdvice getBeforeAdvice() {
return beforeAdvice;
}
public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
this.beforeAdvice = beforeAdvice;
}
public AfterAdvice getAfterAdvice() {
return afterAdvice;
}
public void setAfterAdvice(AfterAdvice afterAdvice) {
this.afterAdvice = afterAdvice;
}
}
// 服务员接口
public interface Waiter {
// 服务
public void serve();
public void shouQian();
}
// 服务员实现类
public class ManWaiter implements Waiter {
public void serve() {
System.out.println("服务中...");
}
public void shouQian() {
System.out.println("收钱!");
}
}
// 前置增强接口
public interface BeforeAdvice {
public void before();
}
// 后置增强接口
public interface AfterAdvice {
public void after();
}
/*
* 目标是让目标对象和增强都可以切换!
*/
public class Demo3 {
@Test
public void fun1() {
ProxyFactory factory = new ProxyFactory();//创建工厂
factory.setTargetObject(new ManWaiter());//设置目标对象
factory.setBeforeAdvice(new BeforeAdvice() {//设置前置增强
public void before() {
System.out.println("您好!");
}
});
factory.setAfterAdvice(new AfterAdvice() {//设置后置增强
public void after() {
System.out.println("再见!");
}
});
Waiter waiter = (Waiter)factory.createProxy();
waiter.shouQian();
waiter.serve();
}
1、AOP 是什么?
都知道面向对象无非是封装、继承、多态,根据某一个类,实例化一个对象,然后操作这一个对象。
AOP 按我自己的理解就是,面向多个对象,或是面向N个对象。
比如我们在service中,可能要对所有的DML操作添加一个transaction,如果说service很少的话,我们可以直接在service中添加一个transaction,那么如果再开发中,有几十个甚至几百个service都需要给他们添加一个transaction,难道我们就写上几十遍、上百遍的transaction。当然不是,在spring中,提供了一个AOP,面向切面的编程,说白了就是面向N个对象的编程,就是将这所有的service中的共同部分提取出来,比如将所有的transaction提取出来,写成一个通知,然后织入(注意别写错字),织入action的代理对象之中,这个actionproxy会先执行织入的通知,然后执行其他。
2、首先明白几个概念(概念可以先略过,还是先后面代码,再来明白吧),
代理模式:代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
Aspect(切面):是通知和切入点的结合,通知和切入点共同定义了关于切面的全部内容---它的功能、在何时和何地完成其功能
joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
Pointcut(切入点):所谓切入点是指我们要对哪些joinpoint进行拦截的定义.
通知定义了切面的”什么”和”何时”,切入点就定义了”何地”.
Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Target(目标对象):代理的目标对象
Weaving(织入):是指把切面应用到目标对象来创建新的代理对象的过程.切面在指定的连接点织入到目标对象
Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
spring在运行期创建代理,不需要特殊的编译器.
spring有两种代理方式:
1.若目标对象实现了若干接口,spring使用JDK的Java.lang.reflect.Proxy类代理。
2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
使用该方式时需要注意:
1.对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统。
对类代理是让遗留系统或无法实现接口的第三方类库同样可以得到通知,
这种方式应该是备用方案。
2.标记为final的方法不能够被通知。spring是为目标类产生子类。任何需要
被通知的方法都被复写,将通知织入。final方法是不允许重写的。
spring只支持方法连接点:不提供属性接入点,spring的观点是属性拦截破坏了
封装。面向对象的概念是对象自己处理工作,其他对象只能通过方法调用的得到的
结果。
3、概念可以先略过。下面写个简单的,来描述下(前置通知)。
比如实现一个功能,就是在所有请求到达action之前为这个请求添加一个日志(先导入spring的必备的jar包),下面的5段代码放在同一个包中即可运行,直接用Java application运行就行
* com.springsource.NET.sf.cglib-2.2.0.jar
cglib代理
* com.springsource.org.aopalliance-1.0.0.jar
* com.springsource.org.aspectj.tools-1.6.6.RELEASE.jar
* org.springframework.aop-3.0.2.RELEASE.jar
spring的面向切面编程,提供AOP(面向切面编程)实现
* org.springframework.aspects-3.0.2.RELEASE.jar
spring提供对AspectJ框架的整合
定义接口
实现:
通知(就是概念中的Advice):
MyMethodBeforeAdvice.java
别忘了继承org.springframework.aop.MethodBeforeAdvice;需要导包
配值spring的配置文件beans.xml
测试:
结果:
我们会发现,我并没有在TestInterface1Impl中的sayHello()和sayh()方法中打印”记录日志“,却发现这里打印了。说明,通知advice已经被执行,是由代理对象帮我们执行。
- 浅析spring中的AOP(面向切面编程)
- 浅析spring中的AOP(面向切面编程)
- Spring AOP(面向切面编程)【AOP中的术语】
- spring 中的aop面向切面编程
- Spring中的AOP面向切面编程
- Spring中的面向切面编程(AOP)简介
- Spring AOP 面向切面编程(一)
- Spring实践:面向切面编程(AOP)
- Spring 的面向切面编程(AOP)
- Spring 面向切面(AOP)编程,注解
- Spring面向切面编程AOP(around)
- Spring AOP(面向切面编程)
- Spring核心AOP(面向切面编程)
- Spring---面向切面编程(aop)实例
- Spring之AOP(面向切面编程)
- Spring自定义面向切面编程(AOP)
- Spring之AOP(面向切面编程)
- spring面向切面编程(aop)
- HTML骨架结构
- 4.24
- [IMWeb训练营]-团队作业
- Linux学习第四单元-管理系统中的简单分区和文件系统
- 3_1决策树(Decision_Tree_ID3)——calcShannonEnt_3_1
- 浅析spring中的AOP(面向切面编程)
- Linq模糊查询
- HTML文档头部
- 题目1376:最近零子序列
- Android仿微信朋友圈,全文收起功能,附源码
- Java正则表达式
- HTML文档声明
- 关于TabLayout和ViewPager联动不显示文字
- Redis ACL之redis_string类分析介绍(一)