spring AOP 两种底层实现( JDK动态代理 和 CGLIB代理)

  AOP的底层实现:

1.底层实现就是代理机制:
          JDK动态代理    CGLIB代理 .
2.JDK动态代理:

         原理:并没有使用多余的技术,纯粹的原java方式,类运用,即生成了一个接口的实现类.

 JDK动态代理的使用:  添加Proxy类,一般会继承: InvocationHandler接口生成invoke方法。

static Object





 InvocationHandler

接口

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

 ClassLoader    :类的加载器.

 Class[]        :实现的所有接口.

 InvocationHandler  :处理接口.


 Object invoke(Object proxy,Method method,Object[] args);

 Object:代理对象.

 Method:执行的方法.

 Object[]:执行这个方法的参数列表.

2.1.调用真实对象的方法的时候;

* UserDao(接口)---->UserDaoImpl(实现类)

UserDaoImpl生成一个代理类.

* UserDao userDao = Proxy.newProxyInstance(..);

* userDao.add();

* userDao.update();

***** 都相当于调用了InvocationHandler中的invoke()方法.

 

2.2.JDK动态代理的代码实现:
    
    
生成代理类==>
public class JdkProxy implements InvocationHandler{
private UserDao userDao;
public JdkProxy(UserDao userDao) {
this.userDao = userDao;
}
public UserDao createProxy(){
Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
return (UserDao) proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 判断执行的方法
// 对add方法进行增强
if("add".equals(method.getName())){
// 增强
System.out.println("增强的代码...");
return method.invoke(userDao, args);
}else{
// 不增强
return method.invoke(userDao, args);
}
}
}
     
     
测试主体 ==>
package cn.green.demo;
import org.junit.Test;
public class TestCase {
@Test
public void demo01(){
UserDao userDao = new UserDaoImpl();
UserDao userProxy = new JdkProxy(userDao).createProxy();
userProxy.add();
userProxy.delete();
}
}
      
      
applicationContext.xml==>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
 
<aop:aspectj-autoproxy />
<bean id="userDao" class="cn.green.demo.UserDaoImpl"></bean>
<bean id="jdkProxy" class="cn.green.demo.JdkProxy"></bean>
 
</beans>

3. CGLIB的代理:

JDK的动态代理有局限性:类必须实现接口,才能生成代理.(一个类没有实现接口,JDK无法生成代理对象.)

CGLIB代理:可以对没有实现接口的类生成代理.

CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate支持它来实现PO(Persistent Object 持久化对象)字节码的动态生成。

* Hibernate  :javassist

原理:

通过字节码技术,对这个类生成了一个子类对象.

   
   
package cn.itcast.spring3.demo2;
 
public class ProductDao {
public void add(){
System.out.println("添加商品...");
}
public void update(){
System.out.println("修改商品...");
}
public void delete(){
System.out.println("删除商品...");
}
public void find(){
System.out.println("查询商品...");
}
}
    
    
package cn.green.demo1;
 
import java.lang.reflect.Method;
 
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
 
public class CglibProxy implements MethodInterceptor {
 
private OrderDao orderDao;
public CglibProxy(OrderDao orderDao){
this.orderDao = orderDao;
}
//生成代理的方法
public OrderDao createProxy(){
//CGLIB核心对象
Enhancer enhancer = new Enhancer();
//原理:对这个类生成一个子类对象
//设置父类
enhancer.setSuperclass(orderDao.getClass());
//设置回调
enhancer.setCallback(this);
//创建代理对象
return (OrderDao) enhancer.create();
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
if("add".equals(method.getName())){
System.out.println("方法前增强代码===============");
Object obj = methodProxy.invokeSuper(proxy, args);
System.out.println("方法后增强代码===============");
return obj;
}else{
return methodProxy.invokeSuper(proxy, args);
}
}
}
    
    
package cn.green.demo1;
import org.junit.Test;
 
public class TestDemo {
@Test
public void test01(){
OrderDao orderDao = new OrderDao();
OrderDao proxy = new CglibProxy(orderDao).createProxy();
proxy.add();
proxy.delete();
proxy.update();
proxy.find();
}
}
   
   
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="orderDao" class="cn.green.demo1.OrderDao"></bean>
<bean id="cglibProxy" class="cn.green.demo1.CglibProxy"></bean>
</beans>
效果如下:
   
   
方法前增强代码===============
add run....
方法后增强代码===============
delete run....
update run....
find run....

4.Spring中使用这两种技术完成代理(AOP):

如果类实现了接口,使用JDK动态代理,为你生成代理对象.

如果类没有实现接口,使用CGLIB动态代理,生成代理对象.

 

总结:

Spring在运行期,生成动态代理对象,不需要特殊的编译器

Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术 为目标Bean执行横向织入

1.若目标对象实现了若干接口,spring使用JDKjava.lang.reflect.Proxy类代理。

2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。

程序中应优先对接口创建代理,便于程序解耦维护

3.标记为final的方法,不能被代理,因为无法进行覆盖

JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰

CGLib 是针对目标类生产子类,因此类或方法 不能使final

4.Spring只支持方法连接点,不提供属性连接.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值