Spring学习笔记之aop动态代理(3)

时间:2022-03-17 22:41:03

Spring学习笔记之aop动态代理(3)

1.0 静态代理模式的缺点:

1、在该系统中有多少的dao就的写多少的proxy,麻烦

2、如果目标接口有方法的改动,则proxy也需要改动。

PersonDao.java

public interface PersonDao {
public void savePerson();
} PersonDaoImpl.java
public class PersonDaoImpl implements PersonDao{
public void savePerson() {
System.out.println("save person");
}
}

PersonDaoProxy.java

public class PersonDaoProxy implements PersonDao{
private PersonDao personDao;
private Transaction transaction;
public PersonDaoProxy(PersonDao personDao,Transaction transaction){
this.personDao = personDao;
this.transaction = transaction;
}
public void savePerson() {
this.transaction.beginTransaction();
this.personDao.savePerson();
this.transaction.commit();
}
}

Transaction.java

public class Transaction {
public void beginTransaction(){
System.out.println("begin transaction");
} public void commit(){
System.out.println("commit");
}
}

ProxyTest.java

/*
* 静态代码模式:
* 1、在该系统中,有多少dao,就得写多少proxy
* 2、如果目标接口有方法的改动,则proxy也得做相应的修改
*/
public class ProxyTest {
@Test
public void testProxy(){
PersonDao personDao = new PersonDaoImpl();
Transaction transaction = new Transaction();
PersonDaoProxy proxy = new PersonDaoProxy(personDao, transaction);
proxy.savePerson();
}
}

2.0 动态代理模式–jdkproxy

(优点:动态的产生代理对象,所以只需要一个拦截器就可以了。

缺点:如果invoke方法做事务的判断,将很复杂。

程序员还是写拦截器了,写拦截器的invoke方法了,所以invoke方法还需要修改)

问题:

1、拦截器的invoke方法在什么时候被调用的

在代理对象调用方法的时候,进入了拦截器中的invoke方法。

2、拦截器总的method参数是什么?在什么时候由实参传递给形参的。

代理对象的方法的名称是什么,method的参数的名称就是什么。

代理对象调用方法的时候进入了拦截器的invoke方法,这个时候传递参数。

3、生成的代理对象实现了接口,代理对象的方法体的内容是什么?

方法体的内容就是拦截器中的invoke方法体的内容。

说明:目标类和代理类实现了共同的接口。

MyInterceptor.java

/**
* 1、引入personDao和Transaction
* 2、完成invoke方法
* @author zd
*
*/
public class MyInterceptor implements InvocationHandler{
private Object target;
private Transaction transaction;
public MyInterceptor(Object target,Transaction transaction){
this.target = target;
this.transaction = transaction;
} public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("savePerson")
||method.getName().equals("updatePerson")){
this.transaction.beginTransaction();
method.invoke(this.target, args);//调用目标类的目标方法
this.transaction.commit();
}else{
method.invoke(this.target, args);//调用目标类的目标方法
}
return null;
}
}

PersonDao.java

public interface PersonDao {
public void savePerson();
} PersonDaoImpl.java
public class PersonDaoImpl implements PersonDao{
public void savePerson() {
System.out.println("save person");
}
}
/*
*
* 问题:
* 1、拦截器中的invoke方法在什么时候被调用的
* 在代理对象调用方法的时候,进入了拦截器中的invoke方法
* 2、拦截器中的method参数是什么?在什么时候由实参传递给形参的
* 代理对象的方法的名称是什么,method参数就是什么
* 代理对象调用方法的时候,进入了拦截器中的invoke方法,这个时候,传递参数
* 3、生成的代理对象实现了接口,代理对象的方法体的内容是什么?
* 方法体的内容就是拦截器中的invoke方法体的内容
*/

Transaction.java

public class Transaction {
public void beginTransaction(){
System.out.println("begin transaction");
}
public void commit(){
System.out.println("commit");
}
}

ProxyTest.java

/**
* jdkproxy的优点
* 动态的产生代理对象,所以只需要用一个拦截器就可以了
* jdkproxy的缺点
* 如果在invoke方法中做事务的判断,将是一件很复杂的事情
* 程序员还是写拦截器了,写拦截器中的invoke方法了,所以invoke方法还需要修改
*
* 说明:
* 目标类和代理类实现了共同的接口
* @author zd
*
*/
public class ProxyTest {
@Test
public void testProxy(){
PersonDao target = new PersonDaoImpl();
Transaction transaction = new Transaction();
MyInterceptor interceptor = new MyInterceptor(target, transaction);
/**
* 第一个参数 目标类的类加载器
* 第二个参数 目标类实现的所有的接口
* 第三个参数 拦截器
*/
PersonDao personDao = (PersonDao)Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), interceptor);
personDao.savePerson();
}
}

3.0 动态代理模式–cglib

jar包cglib-nodep-2.1.3

说明:目标类是代理类的父类。

PersonDaoImpl.java

public class PersonDaoImpl implements PersonDao{
public void savePerson() {
System.out.println("save person");
}
} Transaction.java
public class Transaction {
public void beginTransaction(){
System.out.println("begin transaction");
} public void commit(){
System.out.println("commit");
}
}

MyInterceptor.java

/**
* 1、引入personDao和Transaction
* 2、完成invoke方法
* @author zd
*
*/
public class MyInterceptor implements MethodInterceptor{
private Object target;
private Transaction transaction;
public MyInterceptor(Object target,Transaction transaction){
this.target = target;
this.transaction = transaction;
} public Object createProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);//this代表拦截器对象
enhancer.setSuperclass(target.getClass());//设置代理类的父类为目标类
return enhancer.create();
}
/**
* 该方法的内容和jdkpoxy中的invoke方法的内容是一样的
*/
public Object intercept(Object arg0, Method method, Object[] args,
MethodProxy arg3) throws Throwable {
this.transaction.beginTransaction();
method.invoke(this.target, args);
this.transaction.commit();
return null;
} } PersonDao.java
public interface PersonDao {
public void savePerson();
}

ProxyTest.java

/**
* 目标类是代理类的父类
* @author zd
*
*/
public class ProxyTest {
@Test
public void testProxy(){
PersonDaoImpl target = new PersonDaoImpl();
Transaction transaction = new Transaction();
MyInterceptor interceptor = new MyInterceptor(target, transaction);
PersonDaoImpl proxy = (PersonDaoImpl)interceptor.createProxy();
proxy.savePerson();
}
}

4.0 spring aop的概念

切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事物管理是J2EE应用中一个横切关注点的很好的例子。

在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。

连接点(joinpoint):在程序执行过程中某个特定的点,比如某方法调用时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。

通知(Advice):在切面的某个特定连接点执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知。(通知的类型将在后面部分进行讨论)。

许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。

切入点(Piontcut):匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行。(例如,当执行某个特定名称的方法时)。

切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用Aspect切入点语法。

引入(Introduction):用来给一个模型声明额外的方法或属性(也被称为连接类型声明)(inter-type declaration))。Spring允许引入新的接口(以及一个对应的实现)

到任何被代理的对象。例如,你可以使用引入来使用一个bean实现IsModified接口,以便简化缓存机制。

目标对象(Target Object):被一个或者多个切面所通知的对象。也被称做通知(adviced)对象。既然Spring AOP是通过运行代理实现的,这个对象永远是一个被代理(Proxied)对象。

AOP代理(AOP Proxy):AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

织入(Weaving):把切面连接到其他的应用程序类型或者对象,并创建一个被通知的对象。这些可以编译时(例如使用AspectJ编译器),类加载时和运行时完成。

Spring和其他纯Java AOP框架一样,在运行时完成织入。

JDKProxy代理                          SpringAop
目标对象 目标对象
拦截器类 切面
拦截器类中的方法 通知
被拦截到的目标类中方法的集合 切入点
在客户端调用的方法(目标类目标方法) 连接点
代理类 AOP代理
代理类的代理方法生成的过程 织入 通知根据拦截目标类中的目标方法的位置不一样可以分为:前置通知、后置通知、最终通知、环绕通知、异常通知 说明:
1、通知就是切面中的方法;
2、代理对象的方法=通知+目标方法
3、连接点就是目标接口中的一个方法而已
4、拦截器中的invoke方法就是代理对象的方法=通知+目标方法
5、在现实的开发过程中,通知和目标方法时完全松耦合的 通知:就是切面的方法
织入:形成代理对象的方法的过程就是织入
连接点:客户端调用哪个方法,该方法就是连接点。
只有符合切入点,才让通知和目标方法结合在一起。

Spring学习笔记之aop动态代理(3)的更多相关文章

  1. [Spring学习笔记 4 ] AOP 概念原理以及java动态代理

    一.Spring IoC容器补充(1) Spring IoC容器,DI(依赖注入): 注入的方式:设值方法注入setter(属性注入)/构造子注入(构造函数传入依赖的对象)/字段注入Field(注解) ...

  2. Spring总结七:AOP动态代理的实现

    Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类. 首先我们来用代码简单演示jdk动态代理: 现在有一个商品的增删改查的操作 /** * 商品操作接口 ...

  3. Spring学习笔记2—AOP

    1.AOP概念 AOP(Aspect Oriented Programming):面向切面编程,AOP能够将那些与业务无关,却为业务模块所共同调用的应用(例如事务处理.日志管理.权限控制等)封装起来, ...

  4. Spring学习笔记4——AOP

    AOP 即 Aspect Oriented Program 面向切面编程 首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能. 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务 ...

  5. Spring学习笔记之AOP配置篇(一)

    [TOC] 1. 创建并声明一个切面 首先,创建一个类,添加@Component注解使其添加到IoC容器 然后,添加@Aspect注解,使其成为一个切面 最后,在配置文件里面,使用<aop:as ...

  6. Spring学习笔记(二)Spring基础AOP、IOC

    Spring AOP 1. 代理模式 1.1. 静态代理 程序中经常需要为某些动作或事件作下记录,以便在事后检测或作为排错的依据,先看一个简单的例子: import java.util.logging ...

  7. Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题

    Spring AOP底层的动态代理实现有两种方式:一种是JDK动态代理,另一种是CGLib动态代理. JDK动态代理 JDK 1.3版本以后提供了动态代理,允许开发者在运行期创建接口的代理实例,而且只 ...

  8. 不错的Spring学习笔记&lpar;转&rpar;

    Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是s ...

  9. Spring学习笔记&lpar;一&rpar;

    Spring学习笔记(一) 这是一个沉淀的过程,大概第一次接触Spring是在去年的这个时候,当初在实训,初次接触Java web,直接学习SSM框架(当是Servlet都没有学),于是,养成了一个很 ...

随机推荐

  1. PHP实现实现数字补零格式化

    在接支付SDK的时候,第三方回调处理时需要IP,并且IP的需求是:去掉点号,补零到每地址段3位, 如:192168000001 先看看我的实现: <?php $IP = explode ( '. ...

  2. C&num;集合--Dictionary

    字典(dictionary)是一个集合,其中每个元素都是一个键/值对.字典(Dictionaries)是常用于查找和排序的列表. .NET Framework通过IDictionary接口和IDict ...

  3. 转&colon;Autodesk 2017软件下载&plus;注册机&plus;破解方法&lpar;持续更新&rpar;

    转载自http://blog.sina.com.cn/s/blog_710225790102w03e.html Autodesk 2017安装步骤: 安装Autodesk 2017相关软件 使用序列号 ...

  4. 转:给 C&num; 开发者的代码审查清单

      给 C# 开发者的代码审查清单   [感谢@L就是L 的热心翻译.如果其他朋友也有不错的原创或译文,可以尝试推荐给伯乐在线.] 这是为C#开发者准备的通用性代码审查清单,可以当做开发过程中的参考. ...

  5. Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

    在前阵子,我对实体框架进行了一定的研究,然后把整个学习的过程开了一个系列,以逐步深入的方式解读实体框架的相关技术,期间每每碰到一些新的问题需要潜入研究.本文继续前面的主题介绍,着重从整体性的来总结一下 ...

  6. &lbrack;LintCode&rsqb; Flatten Nested List Iterator 压平嵌套链表迭代器

    Given a nested list of integers, implement an iterator to flatten it. Each element is either an inte ...

  7. 不错的nginx文章,找个时间好好看下。

    http://blog.csdn.net/chosen0ne/article/category/915324

  8. Cable master(二分题 注意精度)

    Cable master Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26596   Accepted: 5673 Des ...

  9. 学无止境,学习AJAX(一)

    什么是AJAX?异步JavaScript和XML. AJAX是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的 ...

  10. PHP安装sqlsrv扩展步骤,PHP如何连接上SQL

    今天捣鼓了一天,终于把PHP的sqlsrc扩展给弄好了.为了让PHP能够顺利连接上MSSQL,实在不易. 第一步:安装Wampserver 我安装的是Wampserver 2.4.17版本.注意:安装 ...