Spring学习之JDK代理和Gclib代理
在Spring框架中,使用JDK动态代理和CGLIB代理是为了支持面向切面编程(AOP)。Spring AOP默认会根据目标bean是否实现接口来选择使用JDK动态代理还是CGLIB代理。这个选择过程是自动的,但您也可以通过配置来显式指定使用哪一种代理方式。
JDK动态代理
JDK动态代理主要用于代理实现了接口的对象。在Spring中,默认情况下,如果目标bean实现了至少一个接口,Spring AOP会使用JDK动态代理。
如何使用
- 定义接口:创建一个或多个接口,定义需要代理的方法。
- 实现接口:创建类实现这些接口。
- 启用AOP:在Spring配置中启用AOP。
package com.phl.aop.pojo;
public interface IUser {
void pay();
}
package com.phl.aop.pojo;
import org.springframework.stereotype.Component;
@Component
public class User implements IUser{
/**
* 支付功能
*/
public void pay(){
System.out.println("用户进行了支付");
}
}
package com.phl.aop.pojo;
public interface IStudent {
String study();
}
package com.phl.aop.pojo;
import org.springframework.stereotype.Component;
@Component
public class Student implements IStudent{
@Override
public String study() {
System.out.println("同学进行了Spring的课程学习");
return "学到了Spring的知识点";
}
public void say_hello(){
System.out.println("SayHello");
}
}
CGLIB代理
如果目标bean没有实现任何接口,Spring AOP会自动使用CGLIB来创建代理。CGLIB代理适用于代理普通的Java类,因为它是通过子类化的方式来实现代理的。
如何使用
- 创建类:创建一个普通的Java类,不需要实现任何接口。
- 启用AOP:在Spring配置中启用AOP。
package com.phl.aop.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Employee {
@Value("1001")
private int empId;
@Value("Tom")
private String empName;
public void details(){
System.out.println("员工信息,工号:"+empId+",姓名:"+empName);
}
}
测试
import com.phl.aop.pojo.*;
import com.phl.aop.proxy.CglibProxy;
import com.phl.aop.proxy.JdkProxy;
import com.phl.aop.proxy.UserProxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring.xml")
public class SpringTest {
//静态代理类
@Resource
private UserProxy userProxy;
//JDK动态代理类
@Resource
private JdkProxy jdkProxy;
@Resource
private IUser user;
@Resource
private IStudent student;
@Resource
private CglibProxy cglibProxy;
@Resource
private Employee employee;
//@Test
public void test1(){
userProxy.pay();
}
//@Test
public void test2(){
// //生成代理类,代理类实现了代理目标的接口
// IUser u = (IUser) jdkProxy.createProxy(user);
// //获取类的类名
// //System.out.println(u.getClass().getName());
// u.pay();
//生成Student类的代理类
IStudent stu = (IStudent) jdkProxy.createProxy(student);
System.out.println(stu.getClass().getName());
String studyResult = stu.study();
System.out.println("学习成果:"+studyResult);
}
//@Test
public void test3(){
Student stu = (Student) cglibProxy.createProxy(student);
stu.study();
//stu.say_hello();
}
@Test
public void test4(){
user.pay();
student.study();
employee.details();
}
}
在上面代码中,自动装配时,对象user和student的类型都必须是接口类型,使用的是JDK代理,因为Student和User实现了IStudent和IUser接口,spring会默认生成JDK代理
而Employee的对象并没有实现接口,所以默认是Cglib代理