当前位置: 首页>后端>正文

java静态代理、动态代理、CGlib、AOP详细讲解

静态代理案列:

第一步: 创建普通的类:

@Data

public class Student {

? ? private String name;

? ? private int age;

}

第二步:创建一个接口,这个接口可以对学生进行操作或不操作

public interface IStudentService {

? ? void save();

? ? Student query(Long id);

}

第三部:创建接口的实现类,这个实现就是要被代理的对象,也叫目标类,实现IStudentService接口

public class StudentServiceImpl implements IStudentService{

? ? @Override

? ? public void save() {

? ? ? ? System.out.println("保存一个学生");

? ? }

? ? @Override

? ? public Student query(Long id) {

? ? ? ? Student student=new Student();

? ? ? ? student.setName("张三");

? ? ? ? student.setAge(20);

? ? ? ? return student;

? ? }

}

第四步:创建增强类和增强方法,在目标对象方法运行的时候进行切入或者增强

public class DaoTranction {

? ? public void before(){

? ? ? ? System.out.println("开启事物之前");

? ? }

? ? public void after(){

? ? ? ? System.out.println("开始事物之后");

? ? }

}

第五步:创建静态代理对象:和目标类实现相同的接口,对外保持相同的服务

public class jingtaidailiduixiang? implements IStudentService{

? ? //指定目标对象

? ? private StudentServiceImpl studentService;

? ? //指定增强类

? ? private DaoTranction daoTranction;

? ? ////通过构造方法出入增强类和要拦截的对象

? ? public jingtaidailiduixiang(StudentServiceImpl studentService, DaoTranction daoTranction) {

? ? ? ? this.studentService = studentService;

? ? ? ? this.daoTranction = daoTranction;

? ? }

? ? @Override

? ? public void save() {

? ? ? ? daoTranction.before();

? ? ? studentService.save();

? ? ? daoTranction.after();

? ? }

? ? @Override

? ? public Student query(Long id) {

? ? ? ? return studentService.query(id);

? ? }

}

第六步:测试

public class test {

? ? public static void main(String[] args) {

? ? ? ? /*

? ? ? ? *? private StudentServiceImpl studentService;

? ? private DaoTranction daoTranction;

? ? * */

? ? ? ? ? //定义指定目标对象

? ? ? ? StudentServiceImpl studentService=new StudentServiceImpl();

? ? ? ? //定义增强类

? ? ? ? DaoTranction daoTranction=new DaoTranction();

? ? ? ? //定义代理对象,并指定该代理对象的目录对象和增强对象

? ? ? ? jingtaidailiduixiang jingtaidailiduixiang=new jingtaidailiduixiang(studentService,daoTranction);

? ? ? ? jingtaidailiduixiang.save();

? ? ? ? jingtaidailiduixiang.query(1L);

? ? }

}

总结:静态代理是的已经写死了目标对象,在编译的时候就确定我要代理哪个对象

动态代理案例:

第一步:定义一个普通类,可以在目标类或接口中操作这个类

@Data

public class Dog {

? ? private String naem;

? ? private int age;

}

第二步:定义接口:

public interface IDogservice {

? ? void save(Dog dog);

? ? Dog query(Long id);

}

第三部:定义接口的实现类,这个实现类会是要被代理的对象,即目标类

public class DogServiceImpl implements IDogservice{

? ? @Override

? ? public void save(Dog dog) {

? ? ? ? System.out.println("保存了一只"+dog);

? ? }

? ? @Override

? ? public Dog query(Long id) {

? ? ? ? Dog dog=new Dog();

? ? ? ? dog.setAge(20);

? ? ? ? dog.setNaem("大黄");

? ? ? ? return null;

? ? }

}

第四步:定义方法拦截器,在方法拦截器中可以指定拦截哪个类的哪个方法,对拦截到方法进行增强处理。这个拦截器必须实现InvocationHandler接口

public class TransactionHandler implements InvocationHandler {

? ? //指定增强方法

? ? private DaoTranction daoTranction;

? ? //指定要拦截的对象

? ? private Object Object;

//通过构造方法出入增强类和要拦截的对象

? ? public TransactionHandler(DaoTranction daoTranction, Object Object) {

? ? ? ? this.daoTranction = daoTranction;

? ? ? ? this.Object = Object;

? ? }

? ? //invoke方法,对要拦截的方法运行,并织入增强方法

? ? @Override

? ? public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {

? ? ? ? ? Object ret=null;

? ? ? ? if(method.getName().equals("save")){

? ? ? ? ? ? daoTranction.before();

? ? ? ? ? ret= method.invoke(Object,objects);

? ? ? ? ? ? daoTranction.after();

? ? ? ? }else {

? ? ? ? ? ret=? method.invoke(Object,objects);

? ? ? ? }

? ? ? ? return ret;

? ? }

}

第五步:测试:

public class test {

? ? public static void main(String[] args) {

? ? ? ? //定义目标对象

? ? ? ? DogServiceImpl dogService=new DogServiceImpl();

? ? ? ? //定义增强类

? ? ? ? DaoTranction daoTranction=new DaoTranction();

? ? ? ? //定义方法拦截器,指定对哪个目标对象进行增强,并且指定增强类

? ? ? ? TransactionHandler transactionHandler=new TransactionHandler(daoTranction,dogService);

//? ? ? ? IDogservice proxy = (IDogservice) Proxy.newProxyInstance(DogServiceImpl.class.getClassLoader(), DogServiceImpl.class.getInterfaces(), transactionHandler);

//? ? ? ? proxy.save();

? ? ? ? IDogservice? o = (IDogservice) Proxy.newProxyInstance(test.class.getClassLoader(), DogServiceImpl.class.getInterfaces(), new InvocationHandler() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

? ? ? ? ? ? ? ? daoTranction.before();

? ? ? ? ? ? ? ? method.invoke(dogService, objects);

? ? ? ? ? ? ? ? return null;

? ? ? ? ? ? }

? ? ? ? });

//? ? ? IDogservice proxy= (IDogservice) Proxy.newProxyInstance(DogServiceImpl.class.getClassLoader(), DogServiceImpl.class.getInterfaces(), transactionHandler);

//? ? ? proxy.save();

//? ? ? ? ? ? Proxy.newProxyInstance(DogServiceImpl.class.getClassLoader(), DogServiceImpl.class.getInterfaces(), new InvocationHandler() {

//

//? ? ? ? ? ? ? ? @Override

//? ? ? ? ? ? ? ? public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

//? ? ? ? ? ? ? ? ? ? return null;

//? ? ? ? ? ? ? ? }

//? ? ? ? ? ? });

//? ? ? ? ? ? Proxy.newProxyInstance(List.class.getClassLoader(), List.class.getInterfaces(), new InvocationHandler() {

//

//? ? ? ? ? ? ? ? @Override

//? ? ? ? ? ? ? ? public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

//? ? ? ? ? ? ? ? ? ? return null;

//? ? ? ? ? ? ? ? }

//? ? ? ? ? ? });

? ? }

}

总结:动态代理是可以指定任意的目标对象,Proxy.newProxyInstance方法可以方便的代理任意目标对象

注意:动态代理和静态代理的目标对象都要实现接口,并且代理代理也是实现了统一的接口

Cglib代理模式:

如果目标对象没有实现接口,我们将无法用静态代理或者动态代理生成代理对象,我们可以通过第三方框架Cglib,来生成目标对象的子类来生成代理对象实现对目标对象的增强

Cglib代理模式案列:

第一步:导入第三方依赖包:

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>cglib</groupId>

? ? ? ? ? ? <artifactId>cglib</artifactId>

? ? ? ? ? ? <version>2.2.2</version>

? ? ? ? </dependency>

第二步创建目标类:

public class StudentServiceImpl{

? ? @Override

? ? public void save(Student student) {

? ? ? ? System.out.println("保有学员信息");

? ? }

? ? @Override

? ? public Student query(Long id) {

? ? ? ? System.out.println("查询操作");

? ? ? ? Student student=new Student();

? ? ? ? student.setName("sy").setAge(20);

? ? ? ? return student;

? ? }

}

第三部:创建cglib拦截器,在拦截器中有个参数是目标类的子类,用子类调用父类的方法,可以在父类方法运行的时候对方法进行增强:

public class Cglibinterceptor implements MethodInterceptor {

? ? //指定增强

? ? private DaoTranaction daoTranaction;

? ? //增强通过构造传入

? ? public Cglibinterceptor(DaoTranaction daoTranaction) {

? ? ? ? this.daoTranaction = daoTranaction;

? ? }

? //参数methodProxy表示目标对象的父类,通过子类调用父类方法,在方法运行是调用增强类的方法对目标对象方法增强

? ? @Override

? ? public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

? ? ? ? daoTranaction.befor();

? ? ? ? Object ret=? methodProxy.invokeSuper(o,objects);

? ? ? ? daoTranaction.after();

? ? ? ? return ret;

? ? }

}

第四步:测试:

public class test {

? ? public static void main(String[] args) {

? ? ? ? //创建一个cglib拦截器,并指定增强类

? ? ? ? Cglibinterceptor cglibinterceptor = new Cglibinterceptor(new DaoTranaction());

? ? ? ? //使用Cglib框架给我们提交了一个Enhancer,用这个类设置父类和拦截器,并创建子类

? ? ? ? Enhancer enhancer = new Enhancer();

? ? ? ? enhancer.setSuperclass(StudentServiceImpl.class);

? ? ? ? enhancer.setCallback(cglibinterceptor);

? ? ? ? IStudentservice iStudentservice? = (IStudentservice) enhancer.create();

? ? ? ? iStudentservice.save(new Student());

? ? }

}

语法上:

① JDK动态代理需要目标类有父接口

② JDK动态代理产生的代理对象是目标类的兄弟

③ CGLIB动态代理不需要父接口,但是目标类不能被final修饰

④ CGLIB动态代理产生的代理对象是目标类的子类

性能上:

① JDK产生代理对象的性能较高;CGLIB较低

② JDK动态代理调用方法的性能较低;CGLIB较高

③ 两者的适用场合不同:

JDK动态代理适合于频繁创建的场景;

如果是单例或对象池的场景(无需频繁创建代理对象),但需要频繁调用代理方法,优先考虑CGLIB动态代理。


https://www.xamrdz.com/backend/3p91938258.html

相关文章: