Spring学习笔记之aop动态代理(3)
2015-10-25 09:32
671 查看
Spring学习笔记之aop动态代理(3)
1.0 静态代理模式的缺点:
1、在该系统中有多少的dao就的写多少的proxy,麻烦
2、如果目标接口有方法的改动,则proxy也需要改动。
PersonDao.java
PersonDaoProxy.java
Transaction.java
ProxyTest.java
2.0 动态代理模式–jdkproxy
(优点:动态的产生代理对象,所以只需要一个拦截器就可以了。
缺点:如果invoke方法做事务的判断,将很复杂。
程序员还是写拦截器了,写拦截器的invoke方法了,所以invoke方法还需要修改)
问题:
1、拦截器的invoke方法在什么时候被调用的
在代理对象调用方法的时候,进入了拦截器中的invoke方法。
2、拦截器总的method参数是什么?在什么时候由实参传递给形参的。
代理对象的方法的名称是什么,method的参数的名称就是什么。
代理对象调用方法的时候进入了拦截器的invoke方法,这个时候传递参数。
3、生成的代理对象实现了接口,代理对象的方法体的内容是什么?
方法体的内容就是拦截器中的invoke方法体的内容。
说明:目标类和代理类实现了共同的接口。
MyInterceptor.java
PersonDao.java
Transaction.java
ProxyTest.java
3.0 动态代理模式–cglib
jar包cglib-nodep-2.1.3
说明:目标类是代理类的父类。
PersonDaoImpl.java
MyInterceptor.java
ProxyTest.java
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框架一样,在运行时完成织入。
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、在现实的开发过程中,通知和目标方法时完全松耦合的 通知:就是切面的方法 织入:形成代理对象的方法的过程就是织入 连接点:客户端调用哪个方法,该方法就是连接点。 只有符合切入点,才让通知和目标方法结合在一起。
相关文章推荐
- Java编程中二维数组的初始化和基本操作实例
- Gradle Plugin Samples 之 Gradle Eclipse Compatible (三)
- eclipse用华为手机调试,用file explorer 打开data/data下的包名导出数据库
- struts2中action的XXX_* metend={1}
- 早晨起来看了看流的概念,又搞出乱码了-.-! 最后解决了。
- struts中关于action的通配符的使用
- java线程池使用
- Java 笔试:算法笔记
- Spring MVC 4.2.2 中最好的集成静态资源的方法
- Java多线程的使用
- eclipse转MyEclipse
- 大四狗:我的java历程(续)
- Java语言基础之多态
- java的接口
- 我遇到的cookie 中文乱码
- Struts2配置文件及相关标签的介绍
- Struts2框架的搭建及配置文件的配置
- Eclipse 安装findbugs插件
- 数据过滤器注解@Filter 如何在hibernate、spring data jpa中调用
- ThinkingInJava_3