1分析代理类的作用与原理及AOP概念
当我们已经开发好了一个类,这时我们需要为这个类添加日志,计数,事务管理 那我们什么做???这时我们可以考虑使用代理。
代理模式是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。
代理分为静态代理和动态代理
1. 代理分类
a) 静态代理:代理类的方法要和接口方式一致!
b) 动态代理,JDK动态代理只能对实现了接口的类进行代理,采用JDK动态代理必须实现InvocationHandler接口,采用Proxy类创建相应的代理类。
c) 动态代理的优缺点:
d) 面向接口编程方便
e) 使用的是Java反射机制 开销比较大。
2. 分析JVM通过反射生成代理类
JDK 1.5 中代理对象的生成,是通过Proxy 类生成的;
1、创建一个实例对象,先找到有参的构造方法。
2、编写一个最简单的InvotationHander
3、调用动态的方法调用动态的实例对象
代码:三种生成代理对象的方法
packageorg.nagi.proxy;
importjava.lang.reflect.Constructor;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
/**
*三种方法生成Collection的代理对象
*@author dell
*
*/
publicclass TestProxy {
privatestaticCollectionc;
publicstaticvoid main(String[] args)throws Exception {
TestProxy.CreateProxy1();
TestProxy.CreateProxy2();
TestProxy.getProxy(c);
}
/**
*
* 第一种生成代理对象
*/
publicstaticvoid CreateProxy1()throws Exception{
//得到代理类
Class classParxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
//得到其构造方法
Constructor con = classParxy.getConstructor(InvocationHandler.class);
//实现InvocationHander接口
class MyInvocationHanderimplements InvocationHandler{
public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}
}
//生成了Collection的一个代理对象
Collection proxy1 = (Collection)con.newInstance(new MyInvocationHander());
}
/**
*
* 第二种生成代理对象
*/
publicstaticvoid CreateProxy2()throws Exception{
//得到代理类
Class classParxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
//得到其构造方法
Constructor con = classParxy.getConstructor(InvocationHandler.class);
//生成了Collection的一个代理对象
Collection proxy1 = (Collection)con.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}
});
}
/**
*
* 第三种生成代理对象
*/
publicstatic Object getProxy(final Object target) {
Object proxy3 = Proxy.newProxyInstance(
//得到目标对象的字节码
target.getClass().getClassLoader(),
//得到目标对象所实现的接口
target.getClass().getInterfaces(),
//实现InvocationHandler接口
new InvocationHandler(){
public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}
}
);
return proxy3;
}
}
2.创建动态类及查看其方法列表信息
3.创建动态类的实例对象及调用其方法
4.完成InvocationHandler对象的内部功能
public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}
5.分析InvocationHandler对象的运行原理
我们在调用代理对象的时候,每一次都执行Invocation 里面Invoke方法,
而在Invoke 方法需要接收三个数据:哪一个代理对象执行,方法、参数;
5.总结分析动态代理类的设计原理与结构
思考:我们在调用代理对象的时候都要执行InvocationHander 接口里面的Invoke()方法;如果有一千个类都需要生成代理对象并且他们所需添加功能不一样 那我们什么办?
这时候我们就需要重构以一下我们的所生成的代理方法,使它可以适应为任何类添加的心新功能和生成代理对象; 我们就引出AOP 的思想;在为一个类生成代理对象的时候,我们只徐告诉它目标和需要添加的方法,为了提高可复用性和灵活性,我们把需要生成代理的类写进配置文件里面。
6.编写可生成代理和插入通告的通用方法
通知的方法:
importjava.lang.reflect.Method;
/**
*通知的借口
*即将插入进来的方法
*如:执行的时间
* 记日记 事务管理
*@author dell
*
*/
publicinterface Adrice {
publicvoid beforeClass(Method method);
publicvoid afterClass(Method method);
}
importjava.lang.reflect.Method;
/**
*实现通知方法
*@author dell
*
*/
publicclass MyAdriceimplements Adrice {
@Override
publicvoid beforeClass(Method method) {
long begain = System.currentTimeMillis();
System.out.println("start....." + begain);
}
@Override
publicvoid afterClass(Method method) {
long after = System.currentTimeMillis();
System.out.println("end....." + after);
}
}
/**
* 万能代理生成器
* @param target需要代理的对象
* @param adrice需要添加的方法
* @return 代理对象
*/
publicstatic Object CreatProxy(final Object target,final Adrice adrice){
Object proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
adrice.beforeClass(method);
Object retVal = method.invoke(target, args);
adrice.afterClass(method);
return retVal;
}
});
return proxy;
}
7.实现类似spring的可配置的AOP框架
首先AOP 存在常用接口:
BeanFactory:负责生产Bean
ProxyFactoryBean:负责生产Bean 代理对象
Adrice: 定义通知的方法接口
Config.properties : 配置为哪一个类产生代理对象
代码:
BeanFactory 工厂类
packageorg.nagi.Aop;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.Properties;
/**
* bean工厂
*@author dell
*
*/
publicclass BeanFactory {
Properties prop = new Properties();
public BeanFactory(InputStream is ) {
try {
//从输入流中加载文件
prop.load(is);
} catch (IOException e) {
e.printStackTrace();
}
}
//通过name得到Bean
public Object getBean(String name)throws Exception{
//从配置文件里面加载类
StringclassName = prop.getProperty(name);
//得到文件内存的字节码
Classclazz = Class.forName(className);
//生成一个代理对象
Objectbean = clazz.newInstance();
// 如果是代理工厂的对相的话,就加载代理目标类,和通知adrice
if(beaninstanceof ProxyFactoryBean){
//如果是代理对象,将其转为ProxyFactoryBean
ProxyFactoryBean proxyFactoryBean =(ProxyFactoryBean)bean;
//加载目标代理类
Object target = Class.forName(prop.getProperty(name +".target")).newInstance();
//加载目标的通知
AopAdvice advice = (AopAdvice) Class.forName(prop.getProperty(name +".advice")).newInstance();
//设置通知
proxyFactoryBean.setAdvice(advice);
//设置代理目标类
proxyFactoryBean.setTarget(target);
Object proxy =proxyFactoryBean.CreatProxy();
return proxy;
}
return bean;
}
}
代理工厂产生类
packageorg.nagi.Aop;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理工厂
* @author dell
*
*/
public classProxyFactoryBean {
private AopAdvice advice;
private Object target;
/**
* 万能代理生成器
*@param target 需要代理的对象
*@param adrice 需要添加的方法
*@return 代理对象
*/
public Object CreatProxy(){
Object proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy,Method method, Object[] args)
throws Throwable {
advice.beforeClass(method);
Object retVal = method.invoke(target,args);
advice.afterClass(method);
return retVal;
}
});
return proxy;
}
public AopAdvice getAdvice() {
return advice;
}
public void setAdvice(AopAdvice advice) {
this.advice = advice;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
通知接口类
packageorg.nagi.Aop;
importjava.lang.reflect.Method;
/**
*通知的借口
*即将插入进来的方法
*如:执行的时间
* 记日记 事务管理
*@author dell
*
*/
publicinterface BaseAdvice {
publicvoid beforeClass(Method method);
publicvoid afterClass(Method method);
}
具体通知实现类
package org.nagi.Aop;
importjava.lang.reflect.Method;
/**
*通知的具体实现类
*@author dell
*
*/
publicclass AopAdviceimplements BaseAdvice{
@Override
publicvoid beforeClass(Method method) {
long begain = System.currentTimeMillis();
System.out.println("start....." + begain);
}
@Override
publicvoid afterClass(Method method) {
long after = System.currentTimeMillis();
System.out.println("end....." + after);
}
}
配置文件:config.properties
nagi=org.nagi.Aop.ProxyFactoryBean
nagi.advice=org.nagi.Aop.AopAdvice
nagi.target=java.util.ArrayList
主函数:
packageorg.nagi.Aop;
importjava.io.InputStream;
/**
*测试类
*@author dell
*
*/
publicclass TestAop {
publicstaticvoid main(String[] args) {
InputStream is = TestAop.class.getResourceAsStream("config.properties");
BeanFactory factory = new BeanFactory(is);
try {
Object nagi = factory.getBean("nagi");
System.out.println(nagi.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果生成一个代理对象:com.sun.proxy.$Proxy0