写点什么

【Java 从 0 到架构师】Spring - 生命周期,mysql 教程入门到精通 pdf

作者:Java高工P7
  • 2021 年 11 月 10 日
  • 本文字数:2427 字

    阅读完需:约 8 分钟

=====================================================================


【Spring AOP】静态代理设计模式、Spring 动态代理开发详解、切入点详解(切入点表达式、切入点函数)


业务层的一些问题




业务层(Service)的主要内容:


  • 业务代码:业务运算、dao 操作等(必要

  • 附加代码:事务、日志、性能监控、异常处理等(可选)



现在的尴尬情况:


  • 在业务层加入附加代码会显得很臃肿、累赘

  • 但很多时候又好像不得不加




类比到生活中的一些问题可以更好的理解:


  • 房东只需要做自己必须要做的事情,其余事情交给中介(代理)去做



对于程序开发而言:


  • 业务层只需要处理好业务代码,其余的事情交给代理去做





代理的作用:在不修改目标类的目标方法代码的前提下,为目标方法增加额外功能


代理类中必须也有同样的目标方法


  • 代理类实现跟目标类同样的接口

  • 若目标类没有实现接口,代理类继承目标类


代理的实现方案:


  • 静态代理 (Static Proxy)


开发人员需要手动编写代理类(创建对应的 *.java 文件)


基本上,一个目标类就需要编写一个代理类


  • 动态代理 (Dynamic Proxy)程序运行过程中动态生成代理类的字节码


静态代理 (Static Proxy)




示例代码:静态代理


要代理 UserServiceImpl,需要实现 UserService 接口(或者继承目标类):


// 代理类实现跟目标类同样的接口


public class UserServiceProxy implements UserService {


private UserService target;


// 为基于 setter 的注入提供条件


public void setTarget(UserService target) {


this.target = target;


}


@Override


public boolean login(String username, String password) {


// 额外操作


System.out.println("日志------------------1");


// 调用目标类的方法实现


boolean result = target.login(username, password);


// 额外操作


System.out.println("日志------------------2");


return result;


}


}


// 代理类继承目标类, 也可实现静态代理


public class SkillServiceProxy extends SkillService {


private SkillService target;


public void setTarget(SkillService target) {


this.target = target;


}


@Override


public boolean save(Object skill) {


System.out.println("SkillServiceProxy - 1");


boolean result = target.save(skill);


System.out.println("SkillServiceProxy - 2");


return result;


}


}


<bean id="userService"


class="com.mj.proxy.UserServiceProxy">


<property name="target">


<bean class="com.mj.service.impl.UserServiceImpl"/>


</property>


</bean>


<bean id="skillService"


class="com.mj.proxy.SkillServiceProxy">


<property name="target">


<bean class="com.mj.service.SkillService"/>


</property>


</bean>


动态代理 (Dynamic Proxy)




动态代理的常见实现方案有 2 种:


  1. JDK 自带:代理类需要实现和目标类一样的接口

  2. 开源项目 CGLib (Code Generation Library):代理类继承目标类


Spring 已经集成了 CGLib


示例代码:Spring - 动态代理


由我们手动实现代理,需要和前面所讲的 Spring 生命周期 BeanPostProcessor 结合起来,拦截每一个 bean 的生命周期,从而实现对每一个 bean 的代理(可以通过判断类名、方法等,来指定哪些对象需要代理)

JDK 动态代理 - Proxy.newProxyInstance

/**


  • 实现 BeanPostProcessor 接口会拦截每一个 bean 的生命周期


*/


public class LogProcessor implements BeanPostProcessor {


@Override


public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {


// 初始化方法调用前不做任何处理


return bean;


}


@Override


public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {


return Proxy.newProxyInstance(


getClass().getClassLoader(), // 类加载器


target.getClass().getInterfaces(), // 代理类需要实现的接口(目标类的接口)


new LogInvocationHandler(target)); // 附加代码


}


private static class LogInvocationHandler implements InvocationHandler {


private final Object target;


public LogInvocationHandler(Object target) {


this.target = target;


}


@Override


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


// proxy:代理对象


// method:目标方法


// args:目标方法的参数


System.out.println("proxy - before");


// 调用目标对象的目标方法(核心业务代码)


Object result = method.invoke(target, args);


System.out.println("proxy - after");


return result;


}


}


}

CGLib 动态代理 - Enhancer、MethodInterceptor

/**


  • 会拦截每一个 bean 的生命周期


*/


public class LogProcessor implements BeanPostProcessor {


@Override


public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {


// 某些类不需要代理


if (!beanName.endsWith("Service")) return target;


Enhancer enhancer = new Enhancer();


// enhancer.setClassLoader(getClass().getClassLoader()); // 可以省略


enhancer.setSuperclass(target.getClass());


enhancer.setCallback(new LogMethodInterceptor(target));


return enhancer.create();


}


// org.speringframework.cglib.proxy.MethodInterceptor


private static class LogMethod


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


Interceptor implements MethodInterceptor {


private final Object target;


public LogMethodInterceptor(Object target) {


this.target = target;


}


@Override


public Object intercept(Object proxy, Method method,


Object[] args, MethodProxy methodProxy)


throws Throwable {


// 可以获取 method 相关信息


// String name = method.getName();


// method.getReturnType();


// method.getParameterTypes();


System.out.println("before");


// 执行目标类的方法


Object result = method.invoke(target, args);


System.out.println("after");

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
【Java从0到架构师】Spring - 生命周期,mysql教程入门到精通pdf