实际这个功能Spring本身就有且做的更好,这里就又造了一下轮子
使用Java自带的Compiler+字符串拼接/模板引擎,也可做,不过这里为了方便直接使用的javassist
使用效果
待代理类
使用
效果
主要部分
注解,非常简单
@Data
public class MBeanInfo {
private CtClass targetClass;
private String group;
private String name;
private String packageName;
private String interfaceName;
private CtClass targetInterface;
@SneakyThrows
public void addMethod(CtMethod method){
targetInterface.addMethod(method);
}
@SneakyThrows
public void addSetterGetter(CtMethod method){
targetClass.addMethod(method);
}
public void init(ClassPool pool) {
targetInterface = pool.makeInterface(packageName + ".$" + interfaceName);
if(group.isEmpty())group=targetClass.getPackageName();//默认使用包名与类名
if(name.isEmpty())name= lowerFirst(targetClass.getSimpleName());
targetClass.setName(targetClass.getPackageName()+".$"+targetClass.getSimpleName());
}
private String lowerFirst(String simpleName) {
char[] array = simpleName.toCharArray();
array[0]|=' ';//类型转小写的小技巧
return new String(array);
}
}
信息包装类型
public class MBeanCreator {
private ClassPool pool;
private MBeanServer mBeanServer;
public MBeanCreator() {
pool = ClassPool.getDefault();
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
@SneakyThrows
public void create(Class<?> clazz) {
if(!clazz.isAnnotationPresent(MBean.class))return;
MBeanInfo mBeanInfo= getMBeanInfo(clazz);
createAndBind(mBeanInfo);
}
@SneakyThrows
private void createAndBind(MBeanInfo mBeanInfo) {
CtClass targetClass = mBeanInfo.getTargetClass();
CtClass targetInterface = mBeanInfo.getTargetInterface();
targetClass.addInterface(targetInterface);
targetClass.writeFile("C:\\Users\\邵康\\Desktop\\MyTest3\\src\\main\\resources");
targetInterface.toClass();// 防止 下面 加载时 找不到上面的类 必须先加载依赖类
Object instance = targetClass.toClass().newInstance();
ObjectName name = new ObjectName(mBeanInfo.getGroup() + ":name=" + mBeanInfo.getName());
mBeanServer.registerMBean(instance,name);
}
@SneakyThrows
private MBeanInfo getMBeanInfo(Class<?> clazz) {
MBeanInfo beanInfo=new MBeanInfo();
CtClass target = pool.get(clazz.getName());
beanInfo.setTargetClass(target);
MBean mBean = (MBean) target.getAnnotation(MBean.class);
beanInfo.setGroup(mBean.group());
beanInfo.setName(mBean.name());
beanInfo.setPackageName(target.getPackageName());
beanInfo.setInterfaceName(target.getSimpleName()+"MBean");
beanInfo.init(pool);
CtMethod[] methods = target.getDeclaredMethods();
for (CtMethod method : methods) {
handleMethod(beanInfo,method);
}
CtField[] fields = target.getDeclaredFields();
for (CtField field : fields) {
handleField(beanInfo,field);
}
return beanInfo;
}
@SneakyThrows
private void handleField(MBeanInfo beanInfo, CtField field) {
String upperFirstName = upperFirst(field.getName());
if(field.hasAnnotation(Getter.class)){
CtMethod getter = CtNewMethod.getter("get" + upperFirstName, field);
doHandleField(beanInfo, getter);
}
if(field.hasAnnotation(Setter.class)){
CtMethod setter = CtNewMethod.setter("set" + upperFirstName, field);
doHandleField(beanInfo,setter);
}
}
private void doHandleField(MBeanInfo beanInfo, CtMethod getter) throws NotFoundException {
beanInfo.addSetterGetter(getter);
doHandleMethod(beanInfo,getter);
}
private String upperFirst(String name) {
char[] array = name.toCharArray();
array[0]&='_';//首字母大写的小技巧
return new String(array);
}
@SneakyThrows
private void handleMethod(MBeanInfo beanInfo, CtMethod method) {
if(!method.hasAnnotation(Operation.class))return;
doHandleMethod(beanInfo, method);
}
private void doHandleMethod(MBeanInfo beanInfo, CtMethod method) throws NotFoundException {
CtMethod ctMethod = new CtMethod(method.getReturnType(), method.getName(), method.getParameterTypes()
, beanInfo.getTargetInterface());
beanInfo.addMethod(ctMethod);
}
}
主要核心类