最近在学java代理类的使用方法,结合了之前看过的注解,想自己实现一个简单的类似于Spring的AutoWire的注解。通过注解的方式给对象的字段生成一个代理类对象。
首先需要一个注解类,这个注解是RunTime时可以读取到的,作用在字段上,通过value来获取该字段指向的实现类
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface AnnoImpl{
String value();
}
一个有方法的接口,以及该接口的实现类
public interface SuperInterface {
void func();
}
public class RealSuper implements SuperInterface {
public void func() {
System.out.println("RealSuper");
}
}
一个Bean对象,里面有上面那个接口的字段,但是这个字段不要new一个对象,里面的run()方法直接调用这个字段的方法。一般会报空指针异常,所以接下来需要实现代理类。
public class WrapperBean{
@AnnoImpl(value = "com.lsj.test.jdkProxy.RealSuper")
SuperInterface superInterface;
public void run(){
superInterface.func();
}
}
大部分准备工作已经做好,现在需要通过cglib来实现为这个Bean对象中superInterface生成一个对象。
代理类通过集成MethodInterceptor,来实现代理,我们需要传入一个Bean对象,来生成这个Bean的代理类。getInstance()网上大部分都有这个方法,通过Enhancer来生成一个代理对象。
intercept()方法是对象每次调用方法时,都会被拦截下来执行intercept()方法,通过intercept()方法来调用原对象的方法,我们可以在原对象调用方法前后添加自己的操作,比如这里,在调用方法前,对调用对象o进行自动装配。
一开始,我通过method.invoke(o,objects)来调用原对象的方法,但是发现会一直循环下去,后面想了一下,原对象每次调用方法,都会被intercept()拦截执行这个intercept()方法,这样就会一直陷入死循环。
public class WrapperProxy implements MethodInterceptor{
private Object target ;
public Object getInstance(Object target ){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
Object object = enhancer.create();
return object;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("========method before========");
// 这里实现自动装配
autoConfig(o);
//method.invoke(o,objects);
methodProxy.invokeSuper(o,objects);
System.out.println("========method atfer========");
return null;
}
public boolean autoConfig(Object object){
boolean result = true;
try {
// 获取所有字段
Field[] fields = target.getClass().getDeclaredFields();
// 遍历字段获取所需要的注解信息
for (Field field : fields) {
Annotation annotation = field.getAnnotation(AnnoImpl.class);
if (annotation != null) {
String classString = ((AnnoImpl) annotation).value();
if(!classString.isEmpty()){
field.setAccessible(true);
field.set(object, Class.forName(classString).newInstance());
field.setAccessible(false);
}
}
}
}catch (Exception e){
result = false;
}
return result;
}
}
主要看里面的autoConfig()方法,这个方法通过获取target对象的所有字段,对这些字段进行遍历获取我之前创建的Annonation。如果该字段的AnnoImpl注解不是空的,则通过反射对这个字段进行赋值。
for (Field field : fields) {
Annotation annotation = field.getAnnotation(AnnoImpl.class);
if (annotation != null) {
//进行赋值操作
String classString = ((AnnoImpl) annotation).value();
if(!classString.isEmpty()){
field.setAccessible(true);
field.set(object, Class.forName(classString).newInstance());
field.setAccessible(false);
}
}
}
main()方法跑起来,不需要new,通过注解以及代理类反射创建字段对象
public class Main {
public static void main(String[] args) {
WrapperProxy wrapperProxy = new WrapperProxy();
WrapperBean wrapperBean = new WrapperBean();
// 获取代理对象
wrapperBean = (WrapperBean) wrapperProxy.getInstance(wrapperBean);
wrapperBean.run();
}
}