今天无事,看了下动态代理模式,就自己写了个通过配置文件添加日志的功能
首先:
1、要使用代理模式,需要一个类实现InvocationHandler接口,并且实现invoke()方法
package com.xingyao.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogInterceptor implements InvocationHandler {
private Object target;
public void before() {
System.out.println("程序运行前");
}
/**
* proxy:这个参数没有用到,在java文档中这样描述的
* (An instance method in a subclass with the same signature
* (name, plus the number and the type of its parameters)
* and return type as an instance method in the superclass
* overrides the superclass's method)
* 就是要求方法签名(名称与参数)与返回类型保持一致
* method:被代理对象的方法执行时需要用到
* args:执行代理对象的方法需要传递的参数
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before();
method.invoke(target, args);
return null;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
这样就能将这个类变成动态代理类
2、然后就是执行动态代理对象
package com.xingyao.service;
import java.lang.reflect.Proxy;
import com.xingyao.aop.LogInterceptor;
import com.xingyao.dao.UserDao;
import com.xingyao.dao.impl.UserDaoImpl;
import com.xingyao.model.User;
public class UserServiceTest {
public static void main(String[] args) {
//被代理对象
UserDao userDAO = new UserDaoImpl();
//代理类的实例
LogInterceptor li = new LogInterceptor();
//将被代理对象传递给代理类
li.setTarget(userDAO);
//返回一个被代理对象化的实例
UserDao userDAOProxy = (UserDao)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), new Class[]{UserDao.class}, li);
//使用这个方法就能在执行userDAO.add()方法的时候添加代理对象的方法
userDAOProxy.add(new User());
}
}
这是没有进行封装的动态代理,每次使用的使用都要new出代理对象出来,然后传递被代理对象,最后得到被代理化的实例。使得程序复杂化
我的改进:通过配置xml文件,将被代理类与代理类进行配置,从而调用getProxy(String idName)方法自动返回一个代理化的实例
1、其中代理类是随着你的需求自己完成
2、配置Resource.xml,配置结构如下
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<!-- 通过配置id的值,得到你需要的代理化对象实例 -->
<type id="user">
<!-- 配置代理类对象的类名 -->
<LogClassName>com.xingyao.aop.LogInterceptor</LogClassName>
<!-- 配置被代理对象的类名 -->
<ProxyName>com.xingyao.dao.impl.UserDaoImpl</ProxyName>
</type>
</resources>
3、调用MyProxy中的getProxy(String idName)方法得到代理化对象
其中该方法实现如下
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.xingyao.Exception.AnalysisException;
import com.xingyao.proxy.utils.ProxyXMLUtils;
public class MyProxy {
public static Object getProxy(String idName) throws AnalysisException {
String logClassName = ProxyXMLUtils.getLogClassName(idName);
String proxyName = ProxyXMLUtils.getProxyName(idName);
try {
Object logClass = Class.forName(logClassName).newInstance();
Object proxyClass = Class.forName(proxyName).newInstance();
Method logSetTargetMethod = logClass.getClass().getDeclaredMethod("setTarget", Object.class);
logSetTargetMethod.invoke(logClass, proxyClass);
return Proxy.newProxyInstance(proxyClass.getClass().getClassLoader(), proxyClass.getClass().getInterfaces(), (InvocationHandler) logClass);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
这里对xml的解析使用的是我专门为Resource.xml专门封装过的ProxyXMLUtils类
4、调用方式如下
package com.xingyao.proxy;
import com.xingyao.Exception.AnalysisException;
import com.xingyao.dao.UserDao;
import com.xingyao.model.User;
import com.xingyao.proxy.MyProxy;
public class MyProxyTest {
public static void main(String[] args) throws AnalysisException {
UserDao userDAOProxy = (UserDao) MyProxy.getProxy("user");
userDAOProxy.add(new User());
}
}
这里就极大的简便了动态代理方法的使用