高新技术之代理
来源:互联网 发布:好听的编程项目名称 编辑:程序博客网 时间:2024/06/02 11:11
代理
生活中的代理:
词面意思:
1. [act as agent]:短时间代人担任职务
2. [act for]:受委托代表当事人进行某种活动。
比如说你想把一份礼物送给某公司的董事长,不需要直接交给董事长,而是交给她的秘书,她的秘书帮忙查看这个礼物是不是危险物品,不是就转交给董事长,这就是代理
程序中的代理:
有一个类已经开发好了,我们要为这个类增加功能,比如说异常处理,日志输出,执行时间等,前提是这个类得方法没有给你,这个时候就需要用到代理了。代理就是在目标的前后增加功能。
代理的重要原则:不要把供货商暴露给你的客户。
图解:
代理类生成及其原理:
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。(理解)
原因:
告诉动态代理类需要实现的方法(接口中方法),所以这个类没有接口就不能实现代理,除非用CGLIB库动态生成这个类的子类(非官方)
代理类具有以下属性:
代理类是公共的、最终的,而不是抽象的。
未指定代理类的非限定名称。但是,以字符串 "$Proxy" 开头的类名空间应该为代理类保留。
代理类会按同一顺序准确地实现其创建时指定的接口。
每个代理类都有一个可以带一个参数(接口 InvocationHandler 的实现)的公共构造方法,用于设置代理实例的调用处理程序。并非必须使用反射 API 才能访问公共构造方法,通过调用 Proxy.newInstance 方法(将调用 Proxy.getProxyClass 的操作和调用带有调用处理程序的构造方法结合在一起)也可以创建代理实例。
如:
创建某一接口 Foo 的代理:
InvocationHandler handler = new MyInvocationHandler(...);
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
Foo f = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });
或使用以下更简单的方法:
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);
第一个参数:传类加载器,因为动态代理是从内存中出来的,没有类加载器,所以要给它指定一个加载器。
第二个参数:类的接口,告诉动态代理类需要实现的方法(接口中的方法),接口可以是多个,所以设置是可变参数。
第三个参数:invocationHandler,必须实现这个接口才能是代理类正常工作。
如果代理接口包含某一方法,它的名称和参数签名与 java.lang.Object 的 hashCode、equals 或 toString 方法相同,那么在代理实例上调用这样的方法时,传递到调用处理程序的 Method 对象将使 java.lang.Object 成为其声明类。(意思是说代理类调用Object里面的方法的时候,除了hashCode(),equals()或toString()这三个方法外都不会交给handler,而直接使用原有方法.)
代理类调用流程:
AOP: Aspect Oriented Programming 面向切面编程。
面向切面编程也叫面向方面:Aspect Oriented Programming(AOP),是目前软件开发中的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP是OOP的延续,是(Aspect Oriented Programming)的缩写,意思是面向切面(方面)编程。
主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
自己写的代理代码
//Bean工厂
public class BeanFactory {
Properties pros = new Properties();
public BeanFactory(InputStream is){
try {
pros.load(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getBean(String name){
//根据键拿到值,这里拿到的是类名
String className = pros.getProperty(name);
Object bean = null;
try {
//实例化此类
bean = Class.forName(className).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//判断是否为代理工厂
if(bean instanceof ProxyFactory){
ProxyFactory proxyFactory = (ProxyFactory)bean;
Object proxy = null;
try {
//使用反射把advice和target键所对应的类实例化,并设置进代理工厂
proxyFactory.setAdvice((Advice) Class.forName(pros.getProperty(name+".advice")).newInstance());
proxyFactory.setTarget(Class.forName(pros.getProperty(name+".target")).newInstance());
//拿到代理类
proxy = proxyFactory.getProxy();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
//代理工厂
public class ProxyFactory {
private Advice advice ;
private Object target;
public ProxyFactory(){
}
//代理方法
public Object getProxy(){
//创建代理类(传入目标的类加载器,目标实现的接口)
Object proxy1 = Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//在方法执行前线调用建议类的方法before();
advice.before();
//调用方法,此方法的对象是target。
Object o = method.invoke(target, args);
//在方法执行后调用建议类的方法after();
advice.after();
//返回执行完方法后返回的结果
return o;
}
});
//返回代理类
return proxy1;
}
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
//我的建议类,继承建议类
public class MyAdvice implements Advice{
// 定义两个方法,分别处理代理前后操作
public void after() {
// TODO Auto-generated method stub
System.out.println("33");
}
public void before() {
// TODO Auto-generated method stub
System.out.println("22");
}
}
//定义接口的好处在于当有多个类时,他们都实现你这个接口,你就可以把类里面的变量改为Adivce,让他来引用子类对象,这样当你要换类的时候,可以直接在配置文件那里改而不需要再在类里面改变量名字了。
public interface Advice {
public void before();
public void after();
}
//测试类
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
//InputStream is = Test.class.getResourceAsStream("config.properties");
//取得配置文件的输入流
InputStream is = Test.class.getClassLoader().getResourceAsStream("beanFactory/config.properties");
//拿到bean
Object bf = new BeanFactory(is).getBean("xxx");
// 代理类不会调用invoke
System.out.println(bf.getClass().getName());
//代理类会调用invoke,因为bf相当于bf.toString().
System.out.println(bf);
}
}
properties文件
#xxx=java.util.ArrayList
xxx=beanFactory.ProxyFactory
xxx.advice=beanFactory.MyAdvice
xxx.target=java.util.ArrayList
- 高新技术之代理
- Java高新技术之代理
- 高新技术之代理
- 黑马程序员---高新技术之动态代理类
- 黑马程序员_高新技术之代理
- 黑马程序员--高新技术之动态代理
- 黑马程序员_java高新技术之动态代理
- 黑马程序员---高新技术之动态代理类
- 黑马程序员----高新技术----之动态代理
- 黑马程序员_高新技术之代理浅谈
- 黑马程序员 java高新技术之代理和AOP原理
- java高新技术—代理
- 黑马程序员 高新技术---代理
- 高新技术<六>---> 代理
- 黑马程序员-高新技术-代理
- 黑马程序员--高新技术--代理
- Java 高新技术(代理)
- 黑马高新技术 代理篇
- 多事之秋
- Silverlight/Windows8/WPF/WP7/HTML5周学习导读(8月5日-8月12日)
- 如何在Django中接收JSON格式的数据
- python利用gzip压缩解压缩StringIO
- Python mechanize gzip response handling
- 高新技术之代理
- [转自豆瓣~]C,C++,C#三者区别
- opencv下调用K均值函数cvKMeans2聚类图像例程
- poj 1066 计算几何构图+最短路
- Oracle RBA 浅谈
- Swing中JInternalFrame窗口平铺、级联等实现
- mac体验具体步骤详解
- JavaBean表单验证
- zz 人脸识别算法初次了解