Spring5 核心概念与代理模式 - 狂神说Java课程笔记
一、Spring概述
1. Spring框架简介
- 轻量级开源框架:解决企业应用开发的复杂性
- 核心特性:IOC、AOP、事务管理、MVC等
- 设计理念:非侵入式设计,代码污染极低
2. Spring优势
- 方便解耦:通过IOC容器降低组件耦合度
- AOP编程支持:面向切面编程,方便实现日志、事务等功能
- 声明式事务:通过配置管理事务,无需硬编码
- 集成各种优秀框架:如MyBatis、Hibernate等
二、IOC(控制反转)
1. 核心概念
// 传统方式:主动创建对象
UserService userService = new UserServiceImpl()
// IOC方式:容器管理对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml")
UserService userService = (UserService) context.getBean("userService")
2. IOC本质
- 控制反转:将对象的创建权交给Spring容器
- 依赖注入:容器负责注入对象所需的依赖
- 好莱坞原则:"Don't call us, we'll call you"
三、依赖注入(DI)
1. 三种注入方式
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg name="name" value="狂神"/>
</bean>
<bean id="user" class="com.kuang.pojo.User">
<property name="name" value="狂神"/>
</bean>
2. 自动装配
- byName:根据属性名自动装配
- byType:根据类型自动装配
- 注解方式:@Autowired、@Resource
四、代理模式
1. 静态代理
实现方式
public interface UserService {
void add();
}
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("添加用户");
}
}
public class UserServiceProxy implements UserService {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
public void add() {
log("before");
userService.add();
log("after");
}
private void log(String msg) {
System.out.println("执行" + msg + "日志");
}
}
优缺点
- 优点:业务类只需关注业务逻辑
- 缺点:接口变化时代理类也需修改;每个真实角色都需要代理类
2. 动态代理
JDK动态代理
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
public Object getProxy() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
private void log(String msg) {
System.out.println("执行了" + msg + "方法");
}
}
UserService target = new UserServiceImpl();
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(target);
UserService proxy = (UserService) pih.getProxy();
proxy.add();
JDK动态代理特点
- 基于接口实现
- 使用Java反射机制
- 代理类在运行时动态生成
3. CGLIB动态代理
实现方式
public class CglibProxy implements MethodInterceptor {
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
public Object getProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("CGLIB代理开始");
Object returnValue = method.invoke(target, args);
System.out.println("CGLIB代理结束");
return returnValue;
}
}
UserService target = new UserServiceImpl();
UserService proxy = (UserService) new CglibProxy(target).getProxyInstance();
proxy.add();
CGLIB特点
- 基于类实现(不需要接口)
- 使用字节码处理框架ASM
- 通过继承方式实现代理
五、三种代理方式对比
| 特性 | 静态代理 | JDK动态代理 | CGLIB动态代理 |
|---|
| 实现方式 | 手动编写代理类 | 基于接口反射 | 基于继承字节码 |
| 编译时 | 需要源码 | 不需要 | 不需要 |
| 性能 | 较高 | 反射调用稍慢 | 字节码生成较快 |
| 灵活性 | 低 | 高 | 高 |
| 适用范围 | 简单场景 | 有接口的场景 | 无接口的场景 |
六、实际应用场景
- Spring AOP:基于动态代理实现
- 事务管理:通过代理实现声明式事务
- 日志记录:统一的日志处理
- 权限控制:方法级别的权限验证
- 性能监控:方法执行时间统计
学习建议
- 理解IOC和DI的设计思想比记住具体实现更重要
- 代理模式是理解Spring AOP的基础,需要重点掌握
- 动手实践:自己实现简单的IOC容器和代理模式
- 结合实际项目理解这些概念的应用场景