5.spring之AOP原理---动态代理

spring中的AOP是通过横向抽取,将分散在各个方法中的重复代码提取出来,在程序编译或运行时通过反射应用到需要执行的地方(区别于静态代理),使开发人员在写业务代码时可以专注于核心业务,而不用过多的关注其它逻辑,如事务管理,日志等。具体是通过AOP框架(spring aop,AspectJ)动态的生成代理对象。
AOP框架生成代理对象有两种方法,JDK动态代理,CGLIB动态代理
jdk代理只能用与实现了接口的,而cglib带不带接口都行

1.JDK动态代理

JDK动态代理是通过java.lang.reflect.proxy实现的
spring会默认使用JDK动态代理来实现AOP

public class UserManagerImpl implements UserManager {  
  
    @Override  
    public void addUser(String userId, String userName) {  
        System.out.println("UserManagerImpl.addUser");  
    }    
}
public class JDKHandler implements InvocationHandler {
    // 目标对象  
    private Object targetObject;  
    //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。              
    public Object newProxyInstance(Object targetObject){  
        this.targetObject=targetObject;  
        //Proxy.newProxyInstance方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例    
        //第一个参数指定产生被代理对象的类加载器,需要将其指定为和目标对象同一个类加载器  
        //第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象(被代理对象)的所有已实现的接口  
        //第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法  
        //根据传入的目标返回一个被代理的对象  
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
                targetObject.getClass().getInterfaces(),this);  
    }  


    @Override  
    //关联的这个实现类的方法被调用时将被执行  
    /*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        System.out.println("start-->>");  
        for(int i=0;i<args.length;i++){  
            System.out.println(args[i]);  
        }  
        Object ret=null;  
    
            /*原对象方法调用前处理日志信息*/  
            System.out.println("satrt-->>");  
              
            //调用目标方法  
            ret=method.invoke(targetObject, args);  
            /*原对象方法调用后处理日志信息*/  
            System.out.println("success-->>");  
            return ret;  
    }  
}

这里在代理类中,一般事务管理,日志记录等都会抽取到一个Aspects(切面)类中,然后在代理类中调用切面类中的方法。
这个代理类中的invoke方法很重要,当代理对象在调用业务方法时(如addUser),就会通过代理类中的Procy.newProxyInstance()方法来调用invoke方法,而且在根据目标对象创建代理对象时,会自动调用一次invoke方法。

以下是测试类:

public class Test {  
  
    public static void main(String[] args){  
      JDKHandler logHandler=new JDKHandler();  
        //创建代理对象
        UserManager userManager=(UserManager)JDKHandler.newProxyInstance(new UserManagerImpl());  
        userManager.addUser("00", "张三");  
    }  
}  
2.CGLIB动态代理

cglib(code generation library)是一个高性能开源的代码生成包,采用底层的字节码技术,对指定目标生成一个子类,并对子类进行增强。2.0版本以后,在spring的核心jar包中已经集成了CGLIB所用的jar包。

//目标类
public class UserDao{
	public void addUser(){
		System.out.println("添加用户");
	}
}
//创建代理类,该类需要实现MethodInterceptor接口,并实现其中的interceptor方法(类似JDK动态代理中的invoke方法)
//代理类
public class CglibProxy implements MethodInterceptor{

	//代理方法
	public Object createProxy(Object target){
		Enhancer enhancer = new Enhancer();
		//确定需要增强的类
		enhancer.setSuperclass(target.getClass());
		//添加回调函数
		enhancer.setCallback(this);
		//返回创建的代理对象
		return enhancer.create();
	}

	/**
	*proxy :CGLIB中根据指定目标类生成的代理对象
	*meyhod:拦截的方法
	*args:拦截方法的参数数组
	*methodProxy:方法的代理对象,用于执行目标类的方法
	*/
	@Override
	public Object intercept(Object proxy,Method method,Object[] args,MethodProcy methodProxy) throws Throwable{
	//创建切面类对象
	MyAspect myAspect = new MyAspect();
	//前增强
	myAspect.check_Permissions();
	//目标方法执行
	Object obj = method.invokeSuper(proxy,args);
	//后增强
	myAspect.log();

	return obj;
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值