-
高新技术五(动态代理类,代理类的作用与原理,AOP框架应用)
2013-06-01 00:17:59...代理类使用过程 :让代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码, 代理是实现AOP编程的核心和关键技术。 2)动态代理: 要为系统中的各种接口的类增加代理功...一.代理类
1.代理类概述
1)代理的作用与理解:
要为已存在的多个具体相同接口的目标类的各个方法增加一些系统功能,
例如:异常处理,日志,计算机方法的运行时间,事务管理,等等,那么就用到了代理类,
代理类使用过程 :让代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码,
代理是实现AOP编程的核心和关键技术。
2)动态代理:
要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,
将会非常麻烦,要写百上千个代理类。
JVM可以在运行期可以自动的动态生成出类的字节码,这种动态生成的类被用作代理类.
JVM生成的动态类必须实现一个或多个接口,所 以JVM生成的动态类只能用作具有相同接口的目标类的代理。
如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库动态生成一个类的子类,这个子类可以作用该类的代理。
2.程序代理代码举例:
class X
{
void sayHello()
{
System.out.println("hello,itcast");
}
}
class XProxy
{
void sayHello()
{
int starttime;
X.sayHello();
int endtime;
}
}
3.程序代理架构图:
Client 接口
客户端调用程序 doSomeThing()
| / ^
| / |
| / |
v / |
Proxy Target
代理类 ------------------> 目标类
doSomeThing() doSomeThing()
{ {
//前置系统功能代码 //业务功能代码
目标对象.doSomeThing() ----> }
//后置系统功能代码
}
4.AOP
1)系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,如下所示:
安全 事务 日志
StudentService----|--------|-------|------
CourseService ----|--------|-------|------
MiscService ----|--------|-------|------
2)用具体的程序代码描述交叉业务:
method1 method2 method3
{ { {
-----------------------------------------------切面
...... ...... ......
-----------------------------------------------切面
} } }
3)交叉业务的编程问题即为面向方面的编程(Aspect oriented program ,简称AOP),
AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,
这与直接在方法中编写切面代码的运行效果是一样的,如下所示:
----------------------------------------------切面
func1 func2 func3
{ [ {
..... .... ....
} } }
----------------------------------------------切面
4)安全,事务,日志等功能要贯穿到好多个模块中,所以,它们是交叉业务。
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
5.创建动态类及查看其方法列表信息代码示例:
public class ProxyTest { /** * @param args */ public static void main(String[] args) throws Exception{ // TODO Auto-generated method stub //得到Collection接口的动态代理类 Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); //遍历打印构造方法 Constructor[] constructors = clazzProxy1.getConstructors(); for(Constructor constructor : constructors){ String name = constructor.getName(); StringBuilder sb = new StringBuilder(name); sb.append("("); Class[] claszzParams = constructor.getParameterTypes(); for(Class classparam : claszzParams){ sb.append(classparam.getName()+","); } if(claszzParams!= null && claszzParams.length!=0) sb.deleteCharAt(sb.length()-1); sb.append(")"); System.out.println(sb.toString()); } //遍历打印Collection集合中方法 Method[] methods = clazzProxy1.getMethods(); for(Method method : methods){ String methodname = method.getName(); StringBuilder sb = new StringBuilder(methodname); sb.append("("); Class[] clazzParams = method.getParameterTypes(); for(Class clazzParam : clazzParams){ sb.append(clazzParam.getName()+","); } if(clazzParams!= null && clazzParams.length!= 0) sb.deleteCharAt(sb.length()-1); sb.append(")"); System.out.println(sb.toString()); }
二.InvocationHandler
1.接口 InvocationHandler(java.lang.reflect)
1)InvocationHandler 是代理实例的调用处理程序 实现的接口。 每个代理实例都具有一个关联的
调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的
invoke 方法。
2)方法摘要
Object invoke(Object proxy, Method method, Object[] args)
在代理实例上处理方法调用并返回结果。
2.使用InvocationHandler对象
//先得到代理类的构造函数再实例化,因为Inovacation没有默认构造器,不能使用clazzProxy1.newInstance(); Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class); class MyInvocationHandler implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return null; } } Collection col = (Collection)constructor.newInstance(new MyInvocationHandler()); System.out.println(col); col.clear(); // col.size(); //用匿名内部类来实现InvocationHandler接口传递给newInstance的参数。 Collection col2 = (Collection)constructor.newInstance(new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return null; } }); 创建动态代理类的第二种方法,直接调用代理类的 newProxyInstance方法。 Object proxy3 = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args)throws Throwable Object retVal = method.invoke(target, args); return retVal; } }
2.分析InvocationHandler对象的运行原理
猜想分析动态生成的类的内部代码:
1).动态生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和
一个如下接受InvocationHandler参数的构造方法。
2)..构造方法接收一个invocationHandler对象,接收对象了要干什么?该方法内部的代码会是怎样的呢?
$Proxy0 implements Collection
{
//拥有InvocationHandler的引用
InvocationHandler handler;
public $Proxy0(InvocationHandler handler)
{
this.handler = handler;
}
}
3)..实现的Collection接口中的各个方法的代码又是怎样的呢?
//生成的Collection接口中的方法的运行原理
int size()
{
return handler.invoke(this,this.getClass().getMethod("size"),null);
}
void clear()
{
handler.invoke(this,this.getClass().getMethod("clear"),null);
}
4)..InvocationHandler接口中定义的invoke方法接收的三个参数又是什么意思?图解说明如下:
Client程序调用objProxy.add("abc")方法时,涉及三要素:objProxy对象,add方法,"abc"参数
Class Proxy$
{
add(Object object)
{
return handler.invoke(Object proxy,Method method,Object[] args);
}
}
5)分析为什么动态类的实例对象的getClass()方法返回了正确结果?
调用代理实例对像从Object类继承的hashCode,equals,或toString这几个方法时,代理对象将调用
请求转发给InvocationHandler对象,对于其他方法,则不转发调用请求。
3.编写可生成代理和插入通告的通用方法。
代码示例:
ArrayList target = new ArrayList();//目标类 Collection proxy3 = (Collection)getProxy(target,new MyAdvice());//代理类 proxy3.add("zxx"); //每调用一次方法就会去调用InvocationHandler的invoke方法。 proxy3.add("lxc"); proxy3.add("lxm"); proxy3.getClass().getName();//在Object类上继承的方法,只有hashCode,equals,toString()会委托InvocationHandler。 System.out.println(proxy3.size()); } private static Object getProxy(final Object target,final Advice advice) { Object proxy3 = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { /*Long beginTime = System.currentTimeMillis(); Object retVal = method.invoke(target, args); Long endTime = System.currentTimeMillis(); System.out.println(method.getName()+"run of time"+(endTime- beginTime)); return retVal;*/ advice.beforeMethod(method);//通告 Object retVal = method.invoke(target, args);//调用目标类方法。 advice.afterMethod(method);//通告 return retVal; } } ); return proxy3; } }
三.实现类似spring的可配置的AOP框架
1)工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法
根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,
则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。
2)BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
#xxx=java.util.ArrayList
xxx=cn.itcast.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.MyAdvice
3)ProxyFactoryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息?
<1>目标
<2>通知
4)编写客户端应用:
<1>编写实现Advice接口的类和在配置文件中进行配置
<2>调用BeanFactory获取对象
2.通过实验了解的知识点
1)Spring的精髓 AOP框架和Bean工厂 。
2)Properties类中方法:
String getProperty(String key)
用指定的键在此属性列表中搜索属性。
void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。
3)JavaBean必须有一个不带参数的构造方法
4) InputStream getResourceAsStream(String name)
把指定文件加载到输入流.
3.代码示例:
/Bean工厂 专用于生产Bean public class BeanFactory { Properties props = new Properties(); public BeanFactory(InputStream ips){ try { props.load(ips); } catch (IOException e) { e.printStackTrace(); } } public Object getBean(String name){ String className = props.getProperty(name); Object bean= null; try { Class clazz = Class.forName(className); bean = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } if(bean instanceof ProxyFactoryBean) { Object proxy = null; try { ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean; Advice advice = (Advice)Class.forName(props.getProperty(name+".advice")).newInstance(); Object target = Class.forName( props.getProperty(name+".target")).newInstance(); proxyFactoryBean.setAdvice(advice); proxyFactoryBean.setTarget(target); proxy = ((ProxyFactoryBean)bean).getProxy(); } catch (Exception e) { e.printStackTrace(); } return proxy; } return bean; } } -------------------------------------- //专用于操作代理类 public class ProxyFactoryBean { private Object target; private Advice advice; public void setTarget(Object target) { this.target = target; } public Object getTarget() { return target; } public void setTarget(String target) { this.target = target; } public Advice getAdvice() { return advice; } public void setAdvice(Advice advice) { this.advice = advice; } public Object getProxy() { // TODO Auto-generated method stub Object proxy = Proxy.newProxyInstance(target.getClass() .getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { advice.beforeMethod(method); Object retVal = method.invoke(target, args); advice.afterMethod(method); return retVal; } }); return proxy; } } ----------------------- 测试类 public class AopFrameworkTest {/** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties"); Object bean = new BeanFactory(ips).getBean("xxx"); System.out.println(bean.getClass().getName()); ((Collection)bean).clear(); } }
-
【Java进阶-Java动态代理与AOP】01 代理类的作用与原理及AOP概念
2017-08-13 22:27:33【Java进阶-Java动态代理】代理类的作用与原理及AOP概念认识代理 代理的概念与作用 生活中的代理,代理商。我们可以通过代理商买东西,而不需要去工厂区买需要的商品。 程序中的代理要为已存在的多个具有相同接口的...【Java进阶-Java动态代理与AOP】01 代理类的作用与原理及AOP概念
认识代理
代理的概念与作用
生活中的代理,代理商。我们可以通过代理商买东西,而不需要去工厂区买需要的商品。程序中的代理
- 要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理等等。
- 编写一个与目标类具有相同接口的代理类,代理类的个每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
静态代理示例
interface StaticProxy{ void method(); } class Target implements StaticProxy{ @Override public void method() { System.out.println("Hello world"); } } class AdvancedTarget implements StaticProxy{ StaticProxy target = new Target(); @Override public void method() { System.out.println("before...."); target.method(); // 调用Target类中的method方法 System.out.println("after...."); } }
编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
Target/AdvancedTarget (目标类和代理类) —-> Interface(目标类和代理类实现相同的接口)
用户类不再直接调用 Target目标类,而是调用 AdvancedTarget 代理类。如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类,这样以后很容易切换,
譬如,想要日志功能时就配置代理类,否则配置目标类,这样增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。AOP
AOP――Aspect oriented program,面向方面的编程(面相切片编程)
系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面。
安全,事务,日志等功能要贯穿到好多个模块中,所以它们就是交叉业务。用具体的程序描述交叉业务
method1 method2 method3 { { { -----------------------------------------------切面1(安全检查,日志记录) ... ... ... -----------------------------------------------切面2(安全检查,日志记录) } } }
交叉业务的编程问题即为面向方面的编程AOP,AOP的目标就是要使交叉业务模块化。
可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。如下所示-----------------------------------------------切面1 func1 func2 func3 { { { ... ... ... } } } -----------------------------------------------切面2
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
只要涉及到AOP,就会有代理。
安全、事务、日志等功能要贯穿到好多个模块中,所以他们就是交叉业务。它们并不是对象。
重要原则:不要把供货商暴露给你的客户。动态代理技术
要为系统中的各种借口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方方式,将是一件复杂的事情!
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
如果目标类没有实现接口,则需要用CGLIB。CGLIB库(开源工具库,不是JVM的标准)可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1.在调用目标方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中
参考:
《Java基础强化教程》 -
黑马程序员_高新技术5(动态代理类,代理类的作用与原理,AOP框架应用)
2013-07-30 14:45:38------- android培训、java培训、期待与您交流! ---------- 一.... ...1)代理的作用与理解: ...要为已存在的多个具体相同接口的...代理类使用过程 :让代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能------- android培训、java培训、期待与您交流! ----------
一.代理类
1.代理类概述
1)代理的作用与理解:
要为已存在的多个具体相同接口的目标类的各个方法增加一些系统功能,
例如:异常处理,日志,计算机方法的运行时间,事务管理,等等,那么就用到了代理类,
代理类使用过程 :让代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码,
代理是实现AOP编程的核心和关键技术。
2)动态代理:
要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,
将会非常麻烦,要写百上千个代理类。
JVM可以在运行期可以自动的动态生成出类的字节码,这种动态生成的类被用作代理类.
JVM生成的动态类必须实现一个或多个接口,所 以JVM生成的动态类只能用作具有相同接口的目标类的代理。
如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库动态生成一个类的子类,这个子类可以作用该类的代理。
2.程序代理代码举例:
class X
{
void sayHello()
{
System.out.println("hello,itcast");
}
}
class XProxy
{
void sayHello()
{
int starttime;
X.sayHello();
int endtime;
}
}
3.程序代理架构图:
Client 接口
客户端调用程序 doSomeThing()
| / ^
| / |
| / |
v / |
Proxy Target
代理类 ------------------> 目标类
doSomeThing() doSomeThing()
{ {
//前置系统功能代码 //业务功能代码
目标对象.doSomeThing() ----> }
//后置系统功能代码
}
4.AOP
1)系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,如下所示:
安全 事务 日志
StudentService----|--------|-------|------
CourseService ----|--------|-------|------
MiscService ----|--------|-------|------
2)用具体的程序代码描述交叉业务:
method1 method2 method3
{ { {
-----------------------------------------------切面
...... ...... ......
-----------------------------------------------切面
} } }
3)交叉业务的编程问题即为面向方面的编程(Aspect oriented program ,简称AOP),
AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,
这与直接在方法中编写切面代码的运行效果是一样的,如下所示:
----------------------------------------------切面
func1 func2 func3
{ [ {
..... .... ....
} } }
----------------------------------------------切面
4)安全,事务,日志等功能要贯穿到好多个模块中,所以,它们是交叉业务。
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
5.创建动态类及查看其方法列表信息
代码示例:
- <span style="font-size:18px;">public class ProxyTest {
- /**
- * @param args
- */
- public static void main(String[] args) throws Exception{
- // TODO Auto-generated method stub
- //得到Collection接口的动态代理类
- Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
- //遍历打印构造方法
- Constructor[] constructors = clazzProxy1.getConstructors();
- for(Constructor constructor : constructors){
- String name = constructor.getName();
- StringBuilder sb = new StringBuilder(name);
- sb.append("(");
- Class[] claszzParams = constructor.getParameterTypes();
- for(Class classparam : claszzParams){
- sb.append(classparam.getName()+",");
- }
- if(claszzParams!= null && claszzParams.length!=0)
- sb.deleteCharAt(sb.length()-1);
- sb.append(")");
- System.out.println(sb.toString());
- }
- //遍历打印Collection集合中方法
- Method[] methods = clazzProxy1.getMethods();
- for(Method method : methods){
- String methodname = method.getName();
- StringBuilder sb = new StringBuilder(methodname);
- sb.append("(");
- Class[] clazzParams = method.getParameterTypes();
- for(Class clazzParam : clazzParams){
- sb.append(clazzParam.getName()+",");
- }
- if(clazzParams!= null && clazzParams.length!= 0)
- sb.deleteCharAt(sb.length()-1);
- sb.append(")");
- System.out.println(sb.toString());
- }</span>
二.InvocationHandler
1.接口 InvocationHandler(java.lang.reflect)
三.实现类似spring的可配置的AOP框架
1)InvocationHandler 是代理实例的调用处理程序 实现的接口。 每个代理实例都具有一个关联的
调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的
invoke 方法。
2)方法摘要
Object invoke(Object proxy, Method method, Object[] args)
在代理实例上处理方法调用并返回结果。
2.使用InvocationHandler对象
- <span style="font-size:18px;">//先得到代理类的构造函数再实例化,因为Inovacation没有默认构造器,不能使用clazzProxy1.newInstance();
- Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
- class MyInvocationHandler implements InvocationHandler{
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- // TODO Auto-generated method stub
- return null;
- }
- }
- Collection col = (Collection)constructor.newInstance(new MyInvocationHandler());
- System.out.println(col);
- col.clear();
- // col.size();
- //用匿名内部类来实现InvocationHandler接口传递给newInstance的参数。
- Collection col2 = (Collection)constructor.newInstance(new InvocationHandler(){
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- // TODO Auto-generated method stub
- return null;
- }
- });
- 创建动态代理类的第二种方法,直接调用代理类的 newProxyInstance方法。
- Object proxy3 = Proxy.newProxyInstance(
- target.getClass().getClassLoader(),
- target.getClass().getInterfaces(),
- new InvocationHandler(){
- public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
- Object retVal = method.invoke(target, args);
- return retVal;
- }
- }
- </span>
2.分析InvocationHandler对象的运行原理
猜想分析动态生成的类的内部代码:
1).动态生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和
一个如下接受InvocationHandler参数的构造方法。
2)..构造方法接收一个invocationHandler对象,接收对象了要干什么?该方法内部的代码会是怎样的呢?
$Proxy0 implements Collection
{
//拥有InvocationHandler的引用
InvocationHandler handler;
public $Proxy0(InvocationHandler handler)
{
this.handler = handler;
}
}
3)..实现的Collection接口中的各个方法的代码又是怎样的呢?
//生成的Collection接口中的方法的运行原理
int size()
{
return handler.invoke(this,this.getClass().getMethod("size"),null);
}
void clear()
{
handler.invoke(this,this.getClass().getMethod("clear"),null);
}
4)..InvocationHandler接口中定义的invoke方法接收的三个参数又是什么意思?图解说明如下:
Client程序调用objProxy.add("abc")方法时,涉及三要素:objProxy对象,add方法,"abc"参数
Class Proxy$
{
add(Object object)
{
return handler.invoke(Object proxy,Method method,Object[] args);
}
}
5)分析为什么动态类的实例对象的getClass()方法返回了正确结果?
调用代理实例对像从Object类继承的hashCode,equals,或toString这几个方法时,代理对象将调用
请求转发给InvocationHandler对象,对于其他方法,则不转发调用请求。
3.编写可生成代理和插入通告的通用方法。
代码示例:
- <span style="font-size:18px;">ArrayList target = new ArrayList();//目标类
- Collection proxy3 = (Collection)getProxy(target,new MyAdvice());//代理类
- proxy3.add("zxx"); //每调用一次方法就会去调用InvocationHandler的invoke方法。
- proxy3.add("lxc");
- proxy3.add("lxm");
- proxy3.getClass().getName();//在Object类上继承的方法,只有hashCode,equals,toString()会委托InvocationHandler。
- System.out.println(proxy3.size());
- }
- private static Object getProxy(final Object target,final Advice advice) {
- Object proxy3 = Proxy.newProxyInstance(
- target.getClass().getClassLoader(),
- target.getClass().getInterfaces(),
- new InvocationHandler(){
- public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
- /*Long beginTime = System.currentTimeMillis();
- Object retVal = method.invoke(target, args);
- Long endTime = System.currentTimeMillis();
- System.out.println(method.getName()+"run of time"+(endTime- beginTime));
- return retVal;*/
- advice.beforeMethod(method);//通告
- Object retVal = method.invoke(target, args);//调用目标类方法。
- advice.afterMethod(method);//通告
- return retVal;
- }
- }
- );
- return proxy3;
- }
- }</span>
1.实现AOP功能的封装与配置
1)工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法
根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,
则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。
2)BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
#xxx=java.util.ArrayList
xxx=cn.itcast.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.MyAdvice
3)ProxyFactoryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息?
<1>目标
<2>通知
4)编写客户端应用:
<1>编写实现Advice接口的类和在配置文件中进行配置
<2>调用BeanFactory获取对象
2.通过实验了解的知识点
1)Spring的精髓 AOP框架和Bean工厂 。
2)Properties类中方法:
String getProperty(String key)
用指定的键在此属性列表中搜索属性。
void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。
3)JavaBean必须有一个不带参数的构造方法
4) InputStream getResourceAsStream(String name)
把指定文件加载到输入流.3.代码示例:
- /Bean工厂 专用于生产Bean
- public class BeanFactory {
- Properties props = new Properties();
- public BeanFactory(InputStream ips){
- try {
- props.load(ips);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public Object getBean(String name){
- String className = props.getProperty(name);
- Object bean= null;
- try {
- Class clazz = Class.forName(className);
- bean = clazz.newInstance();
- } catch (Exception e) {
- e.printStackTrace();
- }
- if(bean instanceof ProxyFactoryBean)
- {
- Object proxy = null;
- try {
- ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
- Advice advice = (Advice)Class.forName(props.getProperty(name+".advice")).newInstance();
- Object target = Class.forName( props.getProperty(name+".target")).newInstance();
- proxyFactoryBean.setAdvice(advice);
- proxyFactoryBean.setTarget(target);
- proxy = ((ProxyFactoryBean)bean).getProxy();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return proxy;
- }
- return bean;
- }
- }
- --------------------------------------
- //专用于操作代理类
- public class ProxyFactoryBean {
- private Object target;
- private Advice advice;
- public void setTarget(Object target) {
- this.target = target;
- }
- public Object getTarget() {
- return target;
- }
- public void setTarget(String target) {
- this.target = target;
- }
- public Advice getAdvice() {
- return advice;
- }
- public void setAdvice(Advice advice) {
- this.advice = advice;
- }
- public Object getProxy() {
- // TODO Auto-generated method stub
- Object proxy = Proxy.newProxyInstance(target.getClass()
- .getClassLoader(), target.getClass().getInterfaces(),
- new InvocationHandler() {
- public Object invoke(Object proxy, Method method,
- Object[] args) throws Throwable {
- advice.beforeMethod(method);
- Object retVal = method.invoke(target, args);
- advice.afterMethod(method);
- return retVal;
- }
- });
- return proxy;
- }
- }
- -----------------------
- 测试类
- public class AopFrameworkTest {/**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- InputStream ips =
- AopFrameworkTest.class.getResourceAsStream("config.properties");
- Object bean = new BeanFactory(ips).getBean("xxx");
- System.out.println(bean.getClass().getName());
- ((Collection)bean).clear();
- }
- }
-
动态代理类
2008-07-23 21:59:13(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容: Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。 Static Class getProxyClass (ClasJava动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。在使用动态代理类时,我们必须实现InvocationHandler接口,以第一节中的示例为例:
抽象角色(之前是抽象类,此处应改为接口):
具体角色RealSubject:同上;
public interface Subject { abstract public void request(); }
代理角色:
import java.lang.reflect.Method; import java.lang.reflect.InvocationHandler; public class DynamicSubject implements InvocationHandler { private Object sub; public DynamicSubject() { } public DynamicSubject(Object obj) { sub = obj; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before calling " + method); method.invoke(sub,args); System.out.println("after calling " + method); return null; } }
该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;此外,在该类还实现了invoke方法,该方法中的
method.invoke(sub,args);
其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,args为执行被代理对象相应操作所需的参数。通过动态代理类,我们可以在调用之前或之后执行一些相关操作。
客户端:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class Client { static public void main(String[] args) throws Throwable { RealSubject rs = new RealSubject(); //在这里指定被代理类 InvocationHandler ds = new DynamicSubject(rs); //初始化代理类 Class cls = rs.getClass(); //以下是分解步骤 /* Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ; Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class}); Subject subject =(Subject) ct.newInstance(new Object[]{ds}); */ //以下是一次性生成 Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds ); subject.request(); }
-
通过源码及代理动态类的源码来分析Java动态代理(jdk和cglib动态代理)
2019-07-15 13:58:11释义:简单的说Java的动态代理即为:代理对象 = 增强代码 + 目标对象(原对象)(类似实现了Python中装饰器的作用) 代理的意义:通过代理实现一系列相似操作,解决代码的臃肿问题(类似于现实生活中的中间商,为每... -
Java动态代理的作用及好处
2019-06-18 15:07:52Java动态代理的优势是实现无侵入式的代码扩展,也就是方法的增强;...在某些情况下,客户不想或者不能直接引用另一个对象,这时候代理对象可以在客户端和目标对象之间起到中介的作用。2.静态代理静态代理类... -
java动态代理有什么作用
2019-07-01 10:24:14作用非常大,在很多底层框架中都会用得到,比如struts,Spring等都用到了动态代理,它的作用很简单,就是将你要使用的类,重新生成一个子类或本类,这样框架就可以利用这个新生成的类做一些事情,比如在该类的方法... -
JAVA动态代理的作用
2015-08-04 12:17:40先定义一个接口类,该接口是我们要代理的接口 public interface Subject { public void rent(); public void hello(String str); } 接下来是一个实现类 public class RealSubject implements Subject,Being { ... -
Java动态代理类及对象的生成流程
2020-04-22 13:19:21在某些情况下,客户不想或者不能直接引用另一个对象,这时候代理对象可以在客户端和目标对象之间起到中介的作用。 举一个实际的例子,比如我想要买一包烟,但生产这包烟的是卷烟厂,我不可能直接去卷烟厂去... -
对代理模式与Java动态代理类的理解
2008-01-09 23:24:00导读: 关键字 对代理模式与Java动态代理类的理解 出处 1. 代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在... -
Java 代理模式与动态代理类
2010-11-21 16:51:51代理模式与Java 动态代理类 文章分类:Java编程 1. 代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而... -
对代理模式与Java动态代理类的理解(转)
2011-02-22 10:23:07对代理模式与Java动态代理类的理解(二转) 文章分类:Java编程 1. 代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个... -
动态与代理AOP--01【代理的作用与概念】【动态代理与AOP】
2014-06-29 11:10:58动态代理与AOP----1代理的作用与概念 动态代理与AOP-----------android培训、java培训、java学习型技术博客、期待与您交流!------------1. 代理的作用与概念1). 代理类使用的背景有一个已经开发好的类,但是现在要... -
Java 动态代理作用
2018-05-10 17:32:13默认排序Intopass程序员,近期沉迷于动漫ING305 人赞同了该回答① 首先你要明白静态代理的作用我们有一个字体提供类,有多种实现(从磁盘,从网络,从系统)public interface FontProvider { Font getFont(String... -
jdk 动态生成代理类
2020-09-11 18:16:031.代理模式:给用户对象提供一个...当委托类方法不满足用户对象时,可以通过代理类来进行委托类的方法拓展而不必直接修改委托类.符合开闭原则.代理类主要进行消息预处理,消息的过滤,转发消息给委托类.代理类并不真正实现 -
java代理模式及动态代理类
2014-07-15 21:12:00代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 代理模式一般涉及到的角色... -
代理模式与java中的动态代理类
2009-08-05 10:52:001. 代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 代理模式一般涉及... -
java类加载器-动态代理类-Properties类使用
2015-01-28 18:35:481 java类加载器-动态代理类 (1)一共3中类加载器,AppClassLoader加载指定的类。java默认加载器 (2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类 (3)BootstrapClassLoader 此... -
动态代理核心类 - ProxyCreatorSupport
2020-05-13 15:51:43动态代理主要的相关类 类 主要作用 AdvisedSupport 注册被代理目标对象、通知,和需要代理的接口 ProxyCreatorSupport 注册和触发监听器,借助DefaultAopProxyFactory获取代理 DefaultAdvisorAdapterRegistry 将...
-
图的遍历
-
QTP自动化测试原理
-
元素周期表-three.js实战详解
-
MMM 集群部署实现 MySQL 高可用和读写分离
-
linux基础入门和项目实战部署系列课程
-
MYSQL企业常用架构与调优经验分享
-
2021年 系统架构设计师 系列课
-
Linux 内核和 Windows 内核有什么区别
-
力扣17. 电话号码的字母组合
-
基于Qt的LibVLC开发教程
-
我与冒泡排序有个约定!
-
晒一下阿里云人工智能方向的ACA证书~~
-
Java学习日记 day1
-
2021 年该学的 CSS 框架 Tailwind CSS 实战视频
-
PHP--简单Demo
-
方法加@Transactional(propagation = Propagation.REQUIRES_NEW)依旧回滚
-
单系统登录机制 VS 多系统登录机制(SSO)
-
php 判断字符串中是否包含另一个字符串
-
基于Netty实现一个类SpringMVC的轻量级Java服务端Web开发框架
-
task2