Spring中的AOP开发
1.代理模式
找个人将你原本想做的事情给做了。
三个部分组成:
抽象主题角色:真实主题和代理主题的共同接口。
真实主题角色:定义了代理角色所代表的真实对象。
代理主题角色:含有对真实主题角色的引用。代理角色通常在将客户端调用传递给真实主题对象之前或者之后执行某些操作。
以收快递的案例:
收快递并签字,这个是抽象主题。
买家,货物的主人,这个是真实主题。
门卫代理收货并签字,这个是代理主题。
代理模式的类图:
实现步骤:
1).定义一个抽象的主题。
package com.jinglin.staticproxy;
/**
* 定义一个抽象的主题,这个主题就规定了方法
* @author sony
*
*/
public interface IGetSomething {
void getsomething();
}
2)实现的是真实主题的类,这个类继承自抽象主题:
public class RealGetSomething implements IGetSomething {
@Override
public void getsomething() {
// TODO Auto-generated method stub
System.out.println("主人亲自收货并签字了");
}
}
3)实现的是代理主题的类,这个类继承自抽象主题,但是这个类关联了所代理的主题对象。
package com.jinglin.staticproxy; /**
* 这是一个代理主题,也需要继承自抽象主题
* @author sony
*
*/
public class ProxyGetSomething implements IGetSomething { private RealGetSomething realGetSomething;//依赖关系 public RealGetSomething getRealGetSomething() {
return realGetSomething;
} public void setRealGetSomething(RealGetSomething realGetSomething) {
this.realGetSomething = realGetSomething;
}
public ProxyGetSomething(RealGetSomething _realGetSomething){
this.realGetSomething=_realGetSomething;
} @Override
public void getsomething() {
// TODO Auto-generated method stub
getbefore();
realGetSomething.getsomething();
getafter();
} private void getbefore(){
System.out.println("检查快递是否是本小区的");
}
private void getafter(){
System.out.println("快递签收完毕");
} }
4)编写客户端调用的类(对外部开放的):
package com.jinglin.staticproxy; public class ClientDemo {
private IGetSomething igetsomething; public IGetSomething getIgetsomething() {
return igetsomething;
} public void setIgetsomething(IGetSomething igetsomething) {
this.igetsomething = igetsomething;
}
public ClientDemo(IGetSomething _igetsomething){
this.igetsomething=_igetsomething;
}
public void show(){
igetsomething.getsomething();
}
}
5)最后编写测试类:
package com.jinglin.test; import org.junit.Test; import com.jinglin.staticproxy.ClientDemo;
import com.jinglin.staticproxy.IGetSomething;
import com.jinglin.staticproxy.ProxyGetSomething;
import com.jinglin.staticproxy.RealGetSomething; public class ProxyStaticTest {
@Test
public void testit(){
RealGetSomething realGetSomething = new RealGetSomething();
IGetSomething igetsomething = new ProxyGetSomething(realGetSomething);
ClientDemo client = new ClientDemo(igetsomething);
client.show();
}
}
2.分析刚才所实现的代理模式的问题
1)实现一个代理,必然要定义一个接口,要实现这个接口。如果一旦代理的内容很多,那么实现的接口就会很多。
2)代理平台,这个代理平台就帮我们实现根据传入的对象来实现代理。
动态代理,模拟mybatis的动态代理
a.首先定义了一个所有数据操作的接口层:
package com.jinglin.mybatis;
/**
* 定义一个接口,这个接口就规定了对数据库的操作
* @author sony
*
*/
public interface ICommandData {
void opdata();
}
b.定义一个继承自这个接口的真实主题对象:
public class DeleteData implements ICommandData { @Override
public void opdata() {
// TODO Auto-generated method stub
System.out.println("这是对于数据库的删除方法");
}
}
另外一个:
public class SelectData implements ICommandData{
@Override
public void opdata() {
// TODO Auto-generated method stub
System.out.println("这是对于数据库的查询的方法");
}
}
c.定义一个动态代理的平台:模拟了一个getMapper方法:
package com.jinglin.mybatis; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class MybatisMapperHandler implements InvocationHandler { private Object obj;
public void getconnection(){
System.out.println("获取连接对象,获取执行命令对象");
}
public void closeconnection(){
System.out.println("执行完毕,关闭连接对象");
}
public Object getMapper(Class<?> classz) throws InstantiationException, IllegalAccessException {
obj = classz.newInstance();
return Proxy.newProxyInstance(classz.getClassLoader(),
classz.getInterfaces(),
this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
getconnection();
Object ret = method.invoke(obj, args);
closeconnection();
return ret;
}
}
最后在测试的时候调用:
public class TestIt {
@Test
public void testit() throws InstantiationException, IllegalAccessException{
MybatisMapperHandler mybatisMapperHandler = new MybatisMapperHandler();
ICommandData icommandData = new SelectData();
ICommandData selectdatamapper=(ICommandData) mybatisMapperHandler.getMapper(icommandData.getClass());
selectdatamapper.opdata(); ICommandData icommandData2 = new DeleteData();
icommandData2 = (ICommandData) mybatisMapperHandler.getMapper(icommandData2.getClass());
icommandData2.opdata();
}
}
4.AOP编程
1)程序代码的构成部分?
通用代码+业务代码
2)开发一个销售记录和进货的功能,每次销售和每次进货都要有日志记录。
业务代码和通用代码的分离的思想,AOP思想,在实际开发的时候将通用代码植入到所需的业务代码中。AOP减少模块间的耦合,低侵入
3)AOP的开发,可以借助于Spring。
Aspect(切面):
将散落于各个业务逻辑之中的Cross-cutting concerns收集起来,设计成各个独立可重用的对象,这些对象称为Aspect
例:动态代理中的LogHandler就是一个Aspect
Advice(增强):在特定的连接点上执行的动作,执行的这个动作就相当于对原始对象的功能做了增强。
Aspect对Cross-cutting concerns(横切关注点)的具体实现称为Advice。
Advice中包括了Cross-cutting concerns的行为或所要提供的服务
例:在动态代理的示例中代理类的invoke()就是Advice的具体实例
Joinpoint(连接点):
Advice在应用程序执行时加入业务流程的点或时机称为Joinpoint,具体来说就是Advice在应用程序中被执行的时机
Spring只支持方法的Joinpoint,执行时机可能是某个方法被执行之前或之后
Pointcut(切入点):切入点就是一系列连接点的集合。
Pointcut定义了感兴趣的Joinpoint,当调用的方法符合Pointcut表示式时,将Advice织入应用程序上提供服务
在Spring中,您可以在定义文件或Annotation中编写Pointcut,说明哪些Advice要应用至方法的前后
Target(目标对象):真正执行业务逻辑的对象
一个Advice被应用的对象或目标对象,也就是被代理的类
例:在动态代理的示例中HelloSpeaker就是LogHandler中Advice的Target
Weave(织入):将切面整合到程序的执行流程中
Advice被应用至对象之上的过程称为织入,在AOP中织入的方式有几个时间点:
编译时期
类加载时期
执行时期
案例:
开发一个商业信息管理系统,这个商业信息管理系统主要的功能就是销售,就是进货。通用功能就是日志记录,权限检查,事务处理等。
1)开发业务类或者通用代码的类。
注意,类与类之间无任何关联。
2)将开发的类加入到spring中,作为bean。
首先修改beans的声明
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- 将bean对象加入到容器中 -->
<!-- 配置业务类的bean-->
<bean id="purchaseservice" class="com.jinglin.aop.service.PurchaseService"></bean>
<bean id="sellservice" class="com.jinglin.aop.service.SellService"></bean>
<!-- 配置切面类的 -->
<bean id="logcommon" class="com.jinglin.aop.common.LogCommon"></bean>
<bean id="rolecommon" class="com.jinglin.aop.common.RoleCommon"></bean>
3)配置AOP的切面:
<!--对于AOP的配置 -->
<aop:config>
<!-- 配置程序执行前的切面类 -->
<aop:aspect id="roleaspect" ref="rolecommon">
<!-- 配置连接点的集合 -->
<aop:pointcut expression="execution(* com..*.*Service.*(..))" id="mypointcut"/>
<!--业务方法执行之前的配置增强 -->
<aop:before method="beforeexecution" pointcut-ref="mypointcut"/>
</aop:aspect>
<!-- 配置程序执行后的切面类 -->
<aop:aspect id="logaspect" ref="logcommon">
<!-- 配置连接点的集合 -->
<aop:pointcut expression="execution(* com..*.*Service.*(..))" id="mypointcut2"/>
<!--业务方法执行之后的配置增强 -->
<aop:after method="afterexecution" pointcut-ref="mypointcut2"/>
</aop:aspect>
</aop:config>
4)编写测试类:
public class AopTest {
static ClassPathXmlApplicationContext ac=null;
static{
ac=new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void aoptest(){
//进货
PurchaseService purchaseService=(PurchaseService) ac.getBean("purchaseservice");
purchaseService.stockit(); //销售
SellService sellService=(SellService) ac.getBean("sellservice");
sellService.sellit();
}
}
Spring中的AOP开发的更多相关文章
- Spring中的AOP
什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...
- Spring中的AOP 专题
Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...
- Spring学习笔记(四)—— Spring中的AOP
一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...
- 2018.12.24 Spring中的aop演示(也就是运用aop技术实现代理模式)
Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 1.spring中的aop演示 aop:面向方面编程.不 ...
- (五)Spring 中的 aop
目录 文章目录 AOP概念 AOP原理 AOP术语 **`Spring`** 中的 **`aop`** 的操作 使用 `AspectJ` 实现 `aop` 的两种方式 AOP概念 浅理解 aop :面 ...
- Spring中关于AOP的实践之概念
一.什么是AOP AOP:也称作面向切面编程 在分享几个概念执行我想先举个栗子(可能例子举得并不是特别恰当): 1.假如路人A走在大街上,被一群坏人绑架了: 2.警察叔叔接到报警迅速展开行动:收集情报 ...
- spring中的AOP 以及各种通知 配置
理解了前面动态代理对象的原理之后,其实还是有很多不足之处,因为如果在项目中有20多个类,每个类有100多个方法都需要判断是不是要开事务,那么方法调用那里会相当麻烦. spring中的AOP很好地解决了 ...
- JavaWeb_(Spring框架)认识Spring中的aop
1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...
- Spring 中基于 AOP 的 @AspectJ
Spring 中基于 AOP 的 @AspectJ @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格. 通过在你的基于架构的 XML ...
随机推荐
- 华为OJ之最长公共子序列
题目描述: 对于两个给定的字符串,给出他们的最长公共子序列. 题目分析: 1,在之前的博文(http://www.cnblogs.com/yonguo123/p/6711360.html)中我们讨论了 ...
- ionic2+Angular ionScroll页面滑动监听
第一:需要在组件中引入相关模块: 第二:如果只是监听页面滑动,只需要标注@ViewChild(Content) content: Content;就可以了. 附加:如果要监听页面的某个元素,并对其进行 ...
- 前端十万个为什么(之一):我们为什么需要npm?
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px ".PingFang SC"; color: #454545 } span ...
- IBATIS动态SQL(1)
转:IBATIS动态SQL 直接使用JDBC一个非常普遍的问题就是动态SQL.使用参数值.参数本身和数据列都是动态SQL,通常是非常困难的.典型的解决办法就是用上一堆的IF-ELSE条件语句和一连串的 ...
- 【D3】D3学习轨迹-----学习到一定层度了再更新
1. 首先了解SVG的基本元素 http://www.w3school.com.cn/svg/ 2. 了解d3的专有名词 http://www.cnblogs.com/huxiaoyun90/p ...
- 【逻辑漏洞】基于BurpSuite的越权测试实战教程
一.什么是越权漏洞?它是如何产生的? 越权漏洞是Web应用程序中一种常见的安全漏洞.它的威胁在于一个账户即可控制全站用户数据.当然这些数据仅限于存在漏洞功能对应的数据.越权漏洞的成因主要是因为开发人员 ...
- ECMAscript6新特性之解构赋值
在以前,我们要对变量赋值,只能直接指定值.比如:var a = 1;var b = 2;但是发现这种写法写起来有点麻烦,一点都不简洁,而在ECMAScript6中引入了一种新的概念,那就是" ...
- Linux(6)文件和磁盘管理
文件和磁盘管理 1. 文件管理ls ls : 查看文件信息. 列出目录的内容 -a :显示指定目录下的所有文件, 包括以.开头的隐藏文件 -l :以列表方式显示文件的详细信息 -h :配合-l显示文件 ...
- Python中的re模块--正则表达式
Python中的re模块--正则表达式 使用match从字符串开头匹配 以匹配国内手机号为例,通常手机号为11位,以1开头.大概是这样13509094747,(这个号码是我随便写的,请不要拨打),我们 ...
- 写个 Hello world - 前端从入坑到弃坑系列教程(1)
这是一个系列教程<前端从入坑到弃坑>的第一篇. HTML 是什么 说白了,HTML 就是网页的内容.比如你现在正在阅读的这个网页的内容,就是 HTML.如果你还不明白,请继续往下阅读. 写 ...