Spring的AOP的底层原理

Spring的AOP  

AOP  Aspect Oriented Programming  面向切面编程

通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP是OOP的扩展和延伸,是为了解决OOP开发遇到的问题

AOP底层实现原理

(只做了解即可,只需要知道如何通过配置生成代理对象)

动态代理

       JDK动态代理     只能对实现了接口的类生成代理对象

       Cglib动态代理(类似于javassist第三方代理技术[ hibernate中通过load方法获取对象,默认是使用javassist技术产生的代理对象 ])    对没有实现接口的类产生代理对象,实质是生成子对象

使用Spring 的 AOP 技术,若使用的类实现了接口,则默认采用JDK动态代理,否则默认采用Cglib动态代理,底层会自动进行切换

JDK动态代理

//接口
public interface UserDao {
	public void save();
	public void fimd();
	public void delete();
	public void update();
}
/**
 * 实现类
 * @author SIHAI
 */
public class UserDaoImp implements UserDao {
	@Override
	public void save() {
		System.out.println("UserDaoImp-save...");
	}
	@Override
	public void fimd() {
		System.out.println("UserDaoImp-find...");
	}
	@Override
	public void delete() {
		System.out.println("UserDaoImp-delete...");
	}
	@Override
	public void update() {
		System.out.println("UserDaoImp-update...");
	}
}

 

/**
 * 使用jdk动态代理产生代理对象
 * @author SIHAI
 */
public class JDKProxy {
	//将要加强的类对象传进来
	public UserDao getProxyUserDao(UserDao dao) {
		return (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//判断是不是save方法
				if("save".equals(method.getName())) {
					//增强
					System.out.println("this place is checked the data ...");
					method.invoke(dao, args);//增强完继续运行原来的方法
				}
				//如果不是,则直接运行这个方法,invoke中的参数表示   方法   是     dao的类型  中拥有   当前方法  所拥有的参数   args
				return method.invoke(dao, args);
			}
		});
	}
}
/**
 * 测试
 * @author SIHAI
 */
public class Test1 {
	/**
	 * 未进行动态代理
	 */
	@Test
	public void train1() {
		UserDao dao = new UserDaoImp();
		dao.save();
		dao.fimd();
		dao.update();
		dao.delete();
	}
	/**
	 * 进行动态代理
	 */
	@Test
	public void train2() {
		UserDao dao = new UserDaoImp();
		UserDao daoProxy = new JDKProxy().getProxyUserDao(dao);
		daoProxy.save();
		daoProxy.fimd();
		daoProxy.update();
		daoProxy.delete();
	}
}

实际开发中,一个项目会有许多许多的dao和dao的实现类,当需求发生改变,需要对原有功能进行加强时,传统的方式是纵向继承,但是这样会要修改每一个dao和他们的实现类,当需求再次改变时,又会是一个巨大的工作量,而Spring的AOP技术为我们解决了这个问题,采用横向抽取机制的方式,即动态代理

Cglib动态代理

Cglib  第三方开源代码生成类库,动态添加类的属性和方法

是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate支持它来实现PO(Persistent Object 持久化对象)字节码的动态生成(现在不用这个了,现在用更强大的Javassist)

/**
 * 
 * @author ysh
 * Customer.java
 * 2018年11月1日  下午12:28:05
 * 被代理类,没有实现接口
 */
public class Customer {
	public void save() {
		System.out.println("saving....");
	}
	public void delete() {
		System.out.println("deleting....");
	}
	public void update() {
		System.out.println("updating....");
	}
	public void find() {
		System.out.println("finding....");
	}
}
/**
 * 
 * @author ysh
 * CglibProxy.java
 * 2018年11月1日  下午12:29:14
 * cglib动态代理生成代理类对象
 */
public class CglibProxy {
	
	private Customer customer;

	public CglibProxy(Customer customer) {
		
		this.customer = customer;
	}
	
	public Customer createProxy() {
		
		//创建Cglib的核心类对象
		Enhancer enhancer = new Enhancer();
		//设置父类
		enhancer.setSuperclass(customer.getClass());
		//设置回调
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
				//查看是否为save方法
				if("save".equals(method.getName())) {
					//增强,比如,在save方法运行前,检查客户权限
					System.out.println("checking...");
					//这里必须要用invokeSuper方法,不能用invoke方法,因为后者会出现死循环????
					return methodProxy.invokeSuper(proxy, args);
				}
				//否则让原来的方法直接运行
				/*proxy是被Customer的代理类对象,即为Customer的子类,
				invokeSuper方法,就是调用proxy的父类的当前方法,
				args用于精确找到要执行的方法,避免重载的影响*/
				return methodProxy.invokeSuper(proxy, args);
			}
		});
		return (Customer) enhancer.create();
	}
}
/**
 * 
 * @author ysh
 * Test1.java
 * 2018年11月1日  下午12:30:22
 * 测试类
 */
public class Test1 {
	
	/**
	 * 传统方式
	 */
	@Test
	public void train1() {
		Customer customer = new Customer();
		customer.save();
		customer.delete();
		customer.find();
		customer.update();
	}
	/**
	 * cglib动态代理
	 */
	@Test
	public void train2() {
		CglibProxy cglibProxy = new CglibProxy(new Customer());
		Customer cus = cglibProxy.createProxy();
		cus.save();
		cus.delete();
		cus.find();
		cus.update();
	}

}

测试结果

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值