Spring spring的cglib动态代理

一.cglib动态代理

1.CGLIB代理:
    1,CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。
    2,要求类不能是final的,要拦截的方法要是非final、非static、非private的。
    3,动态代理的最小单位是类(所有类中的方法都会被处理);

2.在Spring中cglib和jdk代理选择:
  若目标对象实现了若干接口,Spring就会使用JDK动态代理。
  若目标对象没有实现任何接口,Spring就使用CGLIB库生成目标对象的子类。
  对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统,也更符合面向接口编程规。
  cglib和javassist代理的机制都是一样的,都是通过继承实现的.

二.代码示例(Service接口及其实现类,请看上一篇jdk动态代理博文)

 cglib动态代理类:


// 主要针对于类,采用继承于父类
@SuppressWarnings("all")
@Component("cglibProxy")
public class TransactionManagerCallBack implements  org.springframework.cglib.proxy.InvocationHandler {
    @Autowired
    @Qualifier("target")
    private Object target; //真实对象(被代理的对象):在此处指的是EmployeeServiceImpl
    @Autowired
    private TransactionManager txManager;

    // 创建一个代理对象
    public <T>T getProxyObject(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass()); // 设置继承于哪一个父类
        enhancer.setCallback(this); // this是InvocationHandler 增强的对象
        return (T)enhancer.create();  // 创建一个代理对象
    }

    // 在真实对象上做增强操作
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object obj = null;
        txManager.begin();
        try {
            obj = method.invoke(target, args); // 真实对象中的方法
            txManager.commit();
        } catch (Exception e) {
            txManager.rollback();
            e.printStackTrace();
        }

        return obj;
    }
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        ">

    <!-- 解析autowired,resource,qualifier-->
    <context:annotation-config />
    <!--去哪些包下面去扫描组件-->
    <context:component-scan base-package="com.shenzhenair.day02.common" />
    <context:component-scan base-package="com.shenzhenair.day02.cglib_proxy" />


</beans>

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/shenzhenair/day02/cglib_proxy/cglibProxy.xml")
public class cglibProxyTest {
    @Autowired
    @Qualifier("cglibProxy")
    private TransactionManagerCallBack callback;

     //com.sun.proxy.$Proxy15
    @Test
    public void testSave(){
        // 获得代理对象
        // com.shenzhenair.day02.common.service.impl.EmployeeServiceImpl$$EnhancerByCGLIB$$820d8dfb
        IEmployeeService service = callback.getProxyObject();
        System.out.println(service.getClass());
        service.save(new Employee());
    }
}


 

猜你喜欢

转载自blog.csdn.net/m0_38068812/article/details/84482011