原理图:
1、代理构架图:
2、动态代理的工作原理
——————————————————————————————————————————————
一、
通过Proxy的getProxyClass()方法得到代理类的Class对象
通过Class对象反射出所有构造函数以及参数
然后通过Class对象反射出所有方法以及参数
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
public class Test2 {
public static void main(String[] args) {
Class proxyClass=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
// System.out.println(proxyClass.getName());
// System.out.println(String.class.getName());
System.out.println("-----------------构造函数--------------");
/*$Proxy0(java.lang.reflect.InvocationHandler)*/
Constructor[] constructors = proxyClass.getConstructors();
for(Constructor constructor : constructors){
String name = constructor.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = constructor.getParameterTypes();
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("-----------------方法(参数)--------------");
Method[] methods = proxyClass.getMethods();
for(Method method : methods){
String name = method.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = method.getParameterTypes();
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
}
}
二、
创建代理类的方式1:
通过Class对象反射出所有构造函数以及参数
编写一个最简单的InvocationHandler类
调用构造方法创建代理类
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
public class Test2 {
public static void main(String[] args) throws Exception{
Class proxyClass=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
Constructor constructor = proxyClass.getConstructor(InvocationHandler.class);
class MyInvocationHander1 implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
}
Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());
System.out.println(proxy1);
proxy1.clear();//clear()的返回类型是void,代理返回个null,不报错
// proxy1.size();//size()返回类似是int,代理返回了个null,报空指针异常
}
}
创建代理类的方式2:
Proxy提供了一个方法 newProxyInstance( ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
可以直接将类加载器的Class对象,需要实现的所有接口的Class对象的数组,还有InvocationHandler的实例对象 直接传进去,来创建代理类。
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
public class Test2 {
public static void main(String[] args) throws Exception{
//ClassLoader loader, Class<?>[] interfaces, InvocationHandler h
Collection proxy=(Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});
System.out.println(proxy);
proxy.clear();//clear()的返回类型是void,代理返回个null,不报错
// proxy.size();//size()返回类似是int,代理返回了个null,报空指针异常
}
}
三、
改写InvocationHandler的invoke方法,实现其真正代理功能
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class Test2 {
public static void main(String[] args) throws Exception{
Collection proxy=(Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler() {
ArrayList arrayList=new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
{
System.out.println("InvocationHandler的 invoke() 被调用了");
return method.invoke(arrayList, args);
}
});
proxy.add("hello1");
proxy.add("hello1");
proxy.add("hello1");
System.out.println(proxy.size());//size()返回类似是int,代理返回了个null,报空指针异常
}
}
注意:
调用代理对象的从Object类继承的hashCode(),equals()或toString()这几个方法是,代理对象将调用请求转发给Invocation对象,而其他的继承自Object的方法则调用代理类本身的方法
运行代码
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class Test2 {
public static void main(String[] args) throws Exception{
Collection proxy=(Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler() {
ArrayList arrayList=new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
{
System.out.println("InvocationHandler的 invoke() 被调用了");
return method.invoke(arrayList, args);
}
});
System.out.println(proxy.toString());
System.out.println(proxy.getClass().getName());
}
}
说明toString最终用到的是目标类的toString方法,而getClass是代理类自己的
四、创建灵活性更强的动态代理类
代码实现
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class Test2 {
public static void main(String[] args) throws Exception{
Collection collection= (Collection) new MyProxyManger(new ArrayList(),new MyAdvice()).getProxy();
collection.add("xiaozhi");
collection.add("xiaozhi");
collection.remove("xiaozhi");
collection.size();
}
}
class MyProxyManger{
private Object target;
private Advice advice;
public MyProxyManger(Object target, Advice advice) {
super();
this.target = target;
this.advice = advice;
}
public Object getProxy() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
{
advice.beforeMehotd();
System.out.println(method.getName());
Object object=method.invoke(target, args);
advice.afterMehotd();
return object;
}
});
}
}
Advice
public interface Advice {
public abstract void beforeMehotd();
public abstract void afterMehotd();
}
MyAdvice
public class MyAdvice implements Advice {
@Override
public void beforeMehotd() {
System.out.println("-----------------我是方法前调用的!-----------------");
}
@Override
public void afterMehotd() {
System.out.println("-----------------我是方法后调用的!-----------------");
}
}
运行结果
五、实现AOP功能的封装与配置
工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回ProxyFactoryBean对象的getProxy方法返回的代理类。
AopFrameworkTest.java
package com.xiaozhi.proxy;
import java.io.InputStream;
import java.util.Collection;
public class AopFrameworkTest {
public static void main(String[] args) throws Exception {
InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
Object bean = new BeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
((Collection)bean).clear();
}
}
config.properties
#xxx=java.util.ArrayList
xxx=com.xiaozhi.proxy.ProxyFactoryBean
xxx.advice=com.xiaozhi.proxy.MyAdvice
xxx.target=java.util.ArrayList
BeanFactory.java
package com.xiaozhi.proxy;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
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;
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
try {
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.getProxy();
} catch (Exception e) {
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
ProxyFactoryBean.java
package com.xiaozhi.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactoryBean {
private Advice advice;
private Object target;
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 Object getProxy() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
{
advice.beforeMehotd();
System.out.println(method.getName());
Object object=method.invoke(target, args);
advice.afterMehotd();
return object;
}
});
}
}