从反射到SpringAOP

从反射到SpringAOP(编写中)

JDK反射的运用

通过反射做Bean字段操作

Tx tx = new OuterPaymentTx();
tx.setId(12);
tx.setTxHandle("copy test");
tx.setInputor("tttare");
tx.setTxChannel(new TxChannel());
//bean copy
Tx newTx = new OuterPaymentTx();
Class<? extends Object> clazz1 = tx.getClass();
Class<? extends Object> newClazz = newTx.getClass();
System.out.println(clazz1 == newClazz);
List<Field> fieldList = new ArrayList<Field>();
//Tx类的继承关系比较复杂,必须通过while循环拿到此类及所有除Object类以外的父类
//获取此类及其付类所有属性
while(clazz1!=null && !clazz1.getName().toLowerCase().equals("java.lang.object")){
    fieldList.addAll(Arrays.asList(clazz1.getDeclaredFields()));
    clazz1 = clazz1.getSuperclass();
}
//便利属性开始设置
for (int i = 0; i < fieldList.size(); i++) {
    Field field = fieldList.get(i);
    field.setAccessible(true);
    String fieldName = field.getName();
    //Class中被static修饰的字段和方法,静态字段将在metaSpace中类常量池中,无关任何class对象实例
    //静态方法的调用也与class对象实例无关,可被null或者无关对象调用
    Object fieldValue = field.get(tx);//对static修饰的字段,tx换为null或任何值,一样能set值
    //Modifier 配合 Class,Field,Method类的getModifiers()属性
    //能获取 final,static,private等修饰词
    if(!Modifier.isFinal(field.getModifiers())){
        //final不可赋值
        field.setAccessible(true);//setAccessible,破坏类的封装性(private),不建议使用
        field.set(newTx, fieldValue);//对static修饰的字段,newTx换为null或任何值,一样能set值
    }
}
System.out.println(newTx.getId()+"|"+newTx.getInputor()+"|"+newTx.getTxChannel());

通过反射对方法的调用

Class clazz = ParamLogAspect.class;
Method[] declaredMethods = clazz.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
    Method m = declaredMethods[i];
    m.setAccessible(true);
    // Modifier 获取类,字段,方法  private,static,final等修饰属性
    if(Modifier.isStatic(m.getModifiers())&&!m.getName().equals("main")){
        //static,不需要对象实例,用null和其他对象直接调用
        System.out.println(m.invoke(null, "入参"));
    }
 // Modifier用状态和name排除mian方法和不能调用的方法
if(!Modifier.isStatic(m.getModifiers())&&!m.getName().equals("main")&&!m.getName().equals("around"))
   {
        //Method实例调用invoke(Class实例,Objects[]方法参数们)
        System.out.println(m.invoke(clazz.newInstance(), "非静态入参"));
    }
}

JDK实现动态代理

利用jdk的反射实现动态代理,被jdk代理的类一定要实现接口,jdk代理类要实现这个接口,总的来说,jdk代理类与目标类是兄弟关系;

目标对象

/**
 * 核心类,执行程序重要方法,需被代理(不实现Payment无法被jdk代理)
 * */
public class CorePayment implements Payment {

    //核心付款类
    public void execut(String payUserNo,String recieveUserNo,double amount) throws       InterruptedException{
        Thread.sleep(200);
        System.out.println(payUserNo+"向"+recieveUserNo+"付款"+amount);
    }
}

实现动态代理业务逻辑的类

public class JdkProxy  implements InvocationHandler {
    /** 需要代理的目标对象 */
	private Object targetObject;//JdkProxy构造函数时,需要目标类做参数
    
	public Object invoke(Object proxy, Method method, Object[] objects)
			throws Throwable {
		//objects被代理方法的参数,可以进行参数校验
        //method.getName;获取方法名,可以过滤方法
		if(objects.length!=3){
			System.out.println("error:付款信息不全,不能执行付款");
			return null;
		}
		if(CastUtil.toDouble(objects[2])>1000.0){
			System.out.println("error:付款金额过大");
			return null;
		}
		if(CastUtil.toNotNullString(objects[0]).equals("张三")){
			System.out.println("error:张三账户被冻结,不能付款");
			return null;
		}
		try {
            //
			method.invoke(this.targetObject, objects);
			System.out.println("success:成功付款");
		} catch (Exception e) {
			System.out.println("error:付款失败");
			e.printStackTrace();
		}
		return null;
	}   
    
public Object newJdkProxy (Object targetObject){
this.targetObject = targetObject;
//jdk代理,生成代理类需要 目标对象的 classLoader,interface的class对象,和InvocationHandler的实例
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}
}

创建动态代理类的工厂方法

Proxy返回代理对象(目标对象的兄弟对象),需要参数,目标对象的classLoader,目标对象Interfaces的class对象,和处理代理业务的类实例(实现了InvocationHandler接口)

public Object newJdkProxy (Object targetObject){
this.targetObject = targetObject;
//jdk代理,生成代理类需要 目标对象的 classLoader,interface的class对象,和InvocationHandler的实例
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}

测试方法

	public static void main(String[] args) throws InterruptedException {
		JdkProxy jdkProxy = new JdkProxy();
		Payment newJdkProxy = (Payment)jdkProxy.newJdkProxy(new CorePayment());
		newJdkProxy.execut("张三", "李四", 500);
	}

CGlib实现动态代理

cglib需要引入两个jar包:cglib-2.2.2.jar,asm-3.3.1.jar

实现动态代理业务逻辑的类

/**
 * 利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
 * 被代理类和其被代理方法 必须能被继承
 * */
public class CglibProxy implements MethodInterceptor {

	/** CGLib需要代理的目标对象 */
	private Object targetObject;

	/** */
	public Object intercept(Object target, Method method, Object[] objects,
			MethodProxy proxy) throws Throwable {
		System.out.println("被代理方法'"+method.getName()+"'------");
		return method.invoke(this.targetObject, objects);
	}
	
	/**
	 * 生产代理类
	 * */
	public Object newCglibProxy(Object targetObject){
		this.targetObject = targetObject;
        //enhancer对象实现动态代理需要ASM这个字节码操作工具,故如果cglib和asm版本冲突,new此对象会报错
		Enhancer enhancer = new Enhancer();
		//将目标类设置为代理类的父类
		enhancer.setSuperclass(targetObject.getClass());
        //指定实现代理业务的对象(MethodInterceptor的实现类)
		enhancer.setCallback(this);
		return enhancer.create();
	}

}

测试方法

	public static void main(String[] args) throws InterruptedException {
		CglibProxy cglibProxy = new CglibProxy();
		CorePayment corePayment = new CorePayment();
		CorePayment newCglibProxy = (CorePayment)cglibProxy.newCglibProxy(corePayment);
		newCglibProxy.execut("张三", "李四", 100.0);
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值