首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

java动态署理,spring AOP动态代理

2012-11-09 
java动态代理,spring AOP动态代理java动态代理?Proxy.newProxyInstance方法,将动态产生一个类$Proxy0,这个

java动态代理,spring AOP动态代理

java动态代理?Proxy.newProxyInstance方法,将动态产生一个类$Proxy0,这个类既继承了Proxv又实现了所指定类的接口. 该接口有一个方法,令为action,则$Proxy0中实现的action将直接调用InvocationHandler对象的invoke方法.
实现的接口的方法,
?? 动态代理的意义:在函数可能变动的地方,使用动态代理封装这个变化点,让程序员在另一处变动。这处就是继承InvocationHandler的子类中。
?
??? 在程序运行时,让封装点按需要变动。还必须对动态代理进行封装:
??? 在这个封装类中,将使用类反射器。把已经变动好的类文件的路径,传给这个封装类,再经过类反射器得到这个变动好的类。注:这个变动好的类,就是继承了InvocationHandler的类。在下例中,就是指ActionHandler
?
package javaapplication4;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
//---------元接口---------要变动方法所依存的接口
?interface IAction?? {
???? public?? void action();
}
?
//----------元类----------要变动方法所依存的类
?class CAction implements IAction {
??? public void action() {
??????? System.out.println("正在行动");
??? }
}
?
?//---invoke ---就是变更后,所期待的方法.java的proxy 将调用这个类,即方法//invoke
class ActionHandler implements InvocationHandler {
??? private Object actionObj;
??? public Object binder(Object actionObj) {
??????? this.actionObj=actionObj;
??????? return Proxy.newProxyInstance(actionObj.getClass().getClassLoader(),
??????????????? actionObj.getClass().getInterfaces(),this);
??? }
??? public Object invoke(Object proxy, Method method, Object[] args)
??????????? throws Throwable {
??????? Object result = null;
??????? System.out.println("行动前");
??????? try {
??????????? result = method.invoke(actionObj, args);
??????? } catch (Exception e) {
??????? }
??????? System.out.println("行动后");
??????? return result;
??? }
}
?
?
public class Dd {
??? public static void main(String[] args) {
??????? IAction ia = (IAction) new ActionHandler()
??????????????? .binder(new CAction());
??????? ia.action();
??? }
}
??Spring AOP 动态代理?首先你得认识AOP:
AOP ----切面编程
所谓切面编程:在不改变原方法(令为methodA)的定义与使用、也不改变原程序的流程的情况下,变更该methodA的功能。在变更时,最激动人心的时能获得methodA的类的对象,meahtoidA的参数,也可获得mehodA执行的结果,还能得到调用meahtoidA的对象。
??? 简单理解:允许用户在指定地方,插入新的函数,
包括:
1 methodA运行前,执行用户指定的其它方法methodOther,然后返回
2 methodA运行完毕,执行用户指的其它方法methodOther,然后返回
3 , 在执行methodA的地方,变成执行在用户指定的其它方法methodOther,
在methodOther方法中, methodA运不运行,何时运行,随用户自行安排.,然后返回
4 methodA执行出现异常时,执行用户指定的其它方法methodOther,然后返回。
产生动机:
在一个程序中,当我们要 使用一个方法(令为methodA);由于不同的用户对methodA的功能要 求不一样,因此在这个methodA的地方就出现了变化点。所以要在这个变化点上进行封装,留下一个可扩展的接口,便于日后修改维护。
?
本质:
???? 1 Aop核心是一个适配器,把变动前的方法,与变动后的方法联接在一起。
???? 2 这个适配器实现的核心是动态代理Proxy机制
3? 四个核心子接口:
a? MethodBeforeAdvice ----methodA函数调用前执行用户定义的方法
b AfterReturningAdvice ----- methodA函数调后执行用户定义的方法
c MethodInterceptor -------彻底变更MethodA函数为用户定义的方法
d ThrowsAdvice------methodA函数调用出现异常执行用户定义的方法
??????
?
具体实例1 :
?? 有一个购书行为,在购书行为发生前,增加欢迎信息。
?
1 有一购书接口
interface BuyBook {
?? public void buyBook(String customer,String book);
}
?
?2 实现了该接口的对象
?public class MyBuyBook implements BuyBook {
??? public void buyBook(String customer,String book){
??????? System.out.println(customer+"你好你成功购了一本"+book+"!");
???? }
}
?? 3 客户端源代码 test.java
????? package javaapplication2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("myBuyBookTarget ");
??????? buybook.buyBook("小东", "《楚留香》");
??? }
}
2??????? 配置文件 test.xml 位于源代码文件夹下的config文件中。
??<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" value="javaapplication2.BuyBook"/>
??????? <property name="interceptorNames">
??????????? <list>
????????????????? <value>myBeforeAdvice</value>
??????????? </list>
??????? </property>
??????? <property name="target" ref="myBuyBookTarget"/>
??? </bean>
</beans>
?
?
其中:A <bean id="myBeforeAdvice" value="javaapplication2.BuyBook"/>
定义了切面----即要扩展函所依附类所遵循的接口。
?
<property name="interceptorNames">
??????? <list>
????????????? <value>myBeforeAdvice</value>
???????? </list>
??? </property>
所增加的功能,作为list数组的值放进去。即这个数组可放其它三种子接口的对象。如扩展前与扩展后的功能的对象分别是myBeforeAdvice、myAfterAdvice则6中test.xml配置文件仅如下修改,其它地方不变。
<property name="interceptorNames">
??????? <list>
????????????? <value>myBeforeAdvice</value>
????????????? <value>myAfterAdvice</value>
???????? </list>
??? </property>
?
注:此时运行程序,会出现:
欢迎光临!小东!
小东你好你成功购了一本《楚留香》
?
5??????? 完整源代码
a MyBuyBook.java
package javaapplication2;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
?
interface BuyBook {
?? public void buyBook(String customer,String book);
}
?
public class MyBuyBook implements BuyBook {
??? public void buyBook(String customer,String book){
??????? System.out.println(customer+"你好你成功购了一本"+book+"!");
???? }
}
?
class MyBeforeAdvice implements MethodBeforeAdvice {
??? public void before(Method arg0, Object[] arg1, Object target)
??????????? throws Throwable {
??????? String customer=(String)arg1[0];?????
??????? System.out.println("欢迎光临!"+customer+"!");??
??? }
}
?
?
b 测试源代码test.java
package javaapplication2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("buyBook");
??????? buybook.buyBook("小东", "《楚留香》");
??? }
}
?
c 配置文件test.xml见6
????
具体实例2 :
?? 有一个购书行为,在购书行为发生后,增加欢送信息。
?
1 有一购书接口
interface BuyBook {
?? public void buyBook(String customer,String book);
}
?
?2 实现了该接口的对象
?public class MyBuyBook implements BuyBook {
??? public void buyBook(String customer,String book){
??????? System.out.println(customer+"你好你成功购了一本"+book+"!");
???? }
}
?? 3 客户端源代码 test.java
????? package javaapplication2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("myBuyBookTarget ");
??????? buybook.buyBook("小东", "《楚留香》");
??? }
}
4 配置文件 test.xml 位于源代码文件夹下的config文件中。
??<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" value="javaapplication4.BuyBook"/>
??????? <property name="interceptorNames">
??????????? <list>
????????????????? <value>myAfterAdvice</value>
??????????? </list>
??????? </property>
??????? <property name="target" ref="myBuyBookTarget"/>
??? </bean>
</beans>
?
?
其中:A? <bean id="myAfterAdvice" value="javaapplication2.BuyBook"/>
定义了切面----即要扩展函所依附类所遵循的接口。
?
<property name="interceptorNames">
??????? <list>
????????????? <value> myAfterAdvice </value>
???????? </list>
??? </property>
所增加的功能,作为list数组的值放进去。即这个数组可放其它三种子接口的对象。如扩展前与扩展后的功能的对象分别是myBeforeAdvice、myAfterAdvice则6中test.xml配置文件仅如下修改,其它地方不变。
<property name="interceptorNames">
??????? <list>
????????????? <value>myBeforeAdvice</value>
????????????? <value>myAfterAdvice</value>
???????? </list>
??? </property>
?
注:此时运行程序,会出现:
小东你好你成功购了一本《楚留香》
欢迎下次再来!小东!
?
2??????? 完整源代码
a MyBuyBook.java
package javaapplication4;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
?
interface BuyBook {
?? public String buyBook(String customer,String book);
}
?
public class MyBuyBook implements BuyBook {
??? public String buyBook(String customer,String book){
??????? System.out.println(customer+"你好你成功购了一本"+book+"!");
??????? return "aaa";
???? }
}
class MyAfterAdvice implements AfterReturningAdvice {
???? public void afterReturning(Object arg0, Method arg1, Object[] arg2,
????????? Object arg3) throws Throwable {
??????? String customer=(String)arg2[0];?????
??????? System.out.println("欢迎下次再来!"+customer+"!");??
??? }
}
b 测试源代码test.java
?package javaapplication2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("buyBook");
??????? buybook.buyBook("小东", "《楚留香》");
??? }
}
?
c 配置文件test.xml见6
?
具体实例3 :
?? 有一个购书行为,在购书行为发生时,只允许顾客购一本打折书。原来没限制。
?
1 有一购书接口
interface BuyBook {
?? public void buyBook(String customer,String book);
}
?
?2 实现了该接口的对象
?public class MyBuyBook implements BuyBook {
??? public void buyBook(String customer,String book){
??????? System.out.println(customer+"你好你成功购了一本"+book+"!");
???? }
}
?? 3 客户端源代码 test.java
????? package javaapplication2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("myBuyBookTarget ");
??????? buybook.buyBook("小东", "《楚留香》");
??????? buybook.buyBook("小东", "《小李飞刀》");
??? }
}
4 配置文件 test.xml 位于源代码文件夹下的config文件中。
??<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" value="javaapplication4.BuyBook"/>
??????? <property name="interceptorNames">
??????????? <list>
????????????????? <value>myAroundAdvice</value>
??????????? </list>
??????? </property>
??????? <property name="target" ref="myBuyBookTarget"/>
??? </bean>
</beans>
?
?
其中:
A? <bean id="myAroundAdvice" lass="javaapplication4.MyAroundAdvice"/>
定义了扩展了的功能对象
?
<bean id="buyBook" value="javaapplication2.BuyBook"/>
定义了切面----即要扩展函所依附类所遵循的接口。
?
<property name="interceptorNames">
??????? <list>
????????????? <value> myAroundAdvice </value>
???????? </list>
??? </property>
所增加的功能,作为list数组的值放进去。即这个数组可放其它三种子接口的对象。如扩展前与扩展后的功能的对象分别是myAroundAdvice、myAfterAdvice则6中test.xml配置文件仅如下修改,其它地方不变。
<property name="interceptorNames">
??????? <list>
????????????? <value> myAroundAdvice </value>
????????????? <value>myAfterAdvice</value>
???????? </list>
??? </property>
?
注:此时运行程序,会出现:
小东你好你成功购了一本《楚留香》
注意,一名顾客只能买一本打折书!。
7 完整源代码
a MyBuyBook.java
?
package javaapplication4;
import java.util.HashSet;
import java.util.Set;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
?
interface BuyBook {
?? public String buyBook(String customer,String book);
}
public class MyBuyBook implements BuyBook {
??? public String buyBook(String customer,String book){
??????? System.out.println(customer+"你好你成功購了一本"+book+"!");
??????? return "aaa";
???? }
}
?
class MyAroundAdvice implements MethodInterceptor {
?
??? private Set customers=new HashSet();??? //保存购过书的顾客信息
??? public Object invoke(MethodInvocation invocation) throws Throwable {
??? String customer=(String)invocation.getArguments()[0];
??? Object result=null;
??? if(customers.contains(customer)){
???????? System.out.println("注意,一名顾客只能买一本打折书!");
??? } else{
???????? //调用MyBuyBook中的buyBook方法,即真实操作
???????? result=invocation.proceed();??
??? }
??? customers.add(customer);
??? return result;
?}
?
}
?
b 测试源代码test.java
package javaapplication2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("buyBook");
??????? buybook.buyBook("小东", "《楚留香》");
??? }
}
?
c 配置文件test.xml见6
?
具体实例4 :
?? 有一个购书行为,当购《大沙漠》时,这本书已经没有了,发出订货通知。
原来购书时,
1 定义一个异常,完整源码NoThisBookException.xml如下:
?package javaapplication4;
public class NoThisBookException extends RuntimeException {
???? public NoThisBookException(String msg){
????????? super(msg);
???? }
}
2 有一购书接口,其方法要抛出异常
interface BuyBook {
?????? public void buyBook(String customer,String book)throws NoThisBookException;
?
?
?3 实现了该接口的对象
public class MyBuyBook implements BuyBook {
public void buyBook(String customer,String book) throws NoThisBookException{
?????????? if(book.equals("《大沙漠》"))
??????????? throw new NoThisBookException("对不起,没有"+book+"存货了!");
??????????? System.out.println(customer+",你好,你已经购买了一本"+book+"!");
???? }
}
?? 4 客户端源代码 test.java
????? package javaapplication2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??????? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("myBuyBookTarget ");
??????? buybook.buyBook("小东", "《楚留香》");
??????? buybook.buyBook("小东", "《大沙漠》");??? }
}
?
5 配置文件 test.xml 位于源代码文件夹下的config文件中。
??<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" javaapplication4.NoThisBookException: 对不起,没有《大沙漠》存货了
?
6 现在仅修改配置文件,增加一个实现了ThrowsAdvice接口的类,就更改了购书行为buyBook(------小东你好你成功购了一本《楚留香》!
),当发现顾客要购《大沙漠》时,发出订货通知---------“通知仓库,赶紧加订书!”
?public class MyThrowsAdvice implements ThrowsAdvice {
??? //可以定义多个方法,只要传入的参数是不同异常
??? public void afterThrowing(NoThisBookException e){???
???????? System.out.print("通知仓库,赶紧加订书!");
??? }
?
其中:
org.springframework.aop. ThrowsAdvice;接口,允许出现多个
afterThrowing 方法,只要其中的参数是不同异常类型就可以了
?
?
7 修改后的配置文件test.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
??? <bean id="myBuyBookTarget" value="javaapplication4.BuyBook"/>
??????? <property name="interceptorNames">
??????????? <list>
????????????????? <value>myThrowsAdvice</value>
??????????? </list>
??????? </property>
??????? <property name="target" ref="myBuyBookTarget"/>
??? </bean>
</beans>
?
?
其中:
<bean id=" myThrowsAdvice " lass="javaapplication4. MyThrowsAdvice "/>
定义了扩展了的功能对象
?
<bean id="buyBook" value="javaapplication2.BuyBook"/>
定义了切面----即要扩展函所依附类所遵循的接口。
?
<property name="interceptorNames">
??????? <list>
????????????? <value> myThrowsAdvice </value>
???????? </list>
??? </property>
所增加的功能,作为list数组的值放进去。即这个数组可放其它三种子接口的对象。如扩展前与扩展后的功能的对象分别是myThrowsAdvice、myAfterAdvice则6中test.xml配置文件仅如下修改,其它地方不变。
<property name="interceptorNames">
??????? <list>
????????????? <value> myThrowsAdvice </value>
????????????? <value>myAfterAdvice</value>
???????? </list>
??? </property>
?
注:此时运行程序,会出现:
小东你好你成功购了一本《楚留香》
?Exception in thread "main" javaapplication4.NoThisBookException: 对不起,没有《大沙漠》存货了
通知仓库,赶紧加订书!
?8? 完整源代码
a 购书源代码。MyBuyBook.java
package javaapplication4;
?
interface BuyBook {
?????? public void buyBook(String customer,String book)throws NoThisBookException;
//??? public void buyBook(String customer,String book);
}
?
public class MyBuyBook implements BuyBook {
??? public void buyBook(String customer,String book)throws NoThisBookException{
??????? if(book.equals("《大沙漠》"))
??????????? throw new NoThisBookException("对不起,没有"+book+"存货了!");
??????? System.out.println(customer+",你好,你已经购买了一本"+book+"!");
??? }
}
?
b 已经变动的类,必须公共。MyThrowsAdvice.java
?
package javaapplication4;
import org.springframework.aop.ThrowsAdvice;
public class MyThrowsAdvice implements ThrowsAdvice {
??? //可以定义多个方法,只要传入的参数是不同异常
??? public void afterThrowing(NoThisBookException e){???
???????? System.out.print("通知仓库,赶紧加订书!");
??? }
}
?
?
c 异常类源码,必须公共。 NoThisBookException.java
?
?package javaapplication4;
public class NoThisBookException extends RuntimeException {
???? public NoThisBookException(String msg){
????????? super(msg);
???? }
}
?
d 测试类源代码.test.java
?package javaapplication4;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
?
public class test {
??? public static void main(String args[]){
??? ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/config/test.xml");??
??????? BuyBook buybook=(BuyBook)ctx.getBean("buyBook");
??????? buybook.buyBook("小东", "《楚留香》");
??????? buybook.buyBook("小东", "《大沙漠》");
??? }
}
?
e 配置类.test.xml 见7

热点排行