Spring
2023-03-30 08:56:21
本文总阅读量次
BeanFactory是最顶级的接口,是核心容器,定义了getBean()
ApplicationContext接口间接继承了BeanFactory,同时还继承了其他的接口,扩展了功能(例如:国际化、通配符方式获取一组Resource资源、整合Environment环境、事件发布与监听)
- ApplicationContext的实现类组合了BeanFactory。例如:SpringApplication.run()返回的context是ConfigurableApplicationContext继承于ApplicationContext,实现类是AnnotationConfigServletWebServerApplicationContext,组合的BeanFactory的实现类是DefaultListableBeanFactory,这里面就有SingletonObjects
有很多容器的实现类比如:最重要的DefaultListableBeanFactory,还有基于xml的,基于注解的,xxxxApplicationContext这种容器的实现类是组合了DefaultListableBeanFactory。需要通过向这些容器注册BeanDefinition对象,使他们为我们创建Bean。
- 创建Bean的过程
注册了某一个Class的Definition之后,并不会将@Configuration里面的@Bean注册进去,这就需要一些操作来完成这些工作,有很多的后置处理器,这里也用到了模板设计模式。
- 后置处理器:
- BeanFactory的后置处理器,可以解析@Configuration里面的@Bean
- Bean的后置处理器,可以解析@Autowired,@Resource
- 模板方法模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public class TemplateMethodPattern {
interface Processor {
void method();
}
public static class Student {
private final List<Processor> list = new ArrayList<>();
private final String name = "Tom";
public void stuMethod() {
System.out.println("name: " + name + "do something...");
for (Processor processor : list) {
processor.method();
}
}
public void addProcessor(Processor processor) {
list.add(processor);
}
}
public static void main(String[] args) {
Student student = new Student();
student.addProcessor(() -> System.out.println("扩展1"));
student.addProcessor(() -> System.out.println("扩展2"));
student.stuMethod();
}
}
- 后置处理器:
Bean的生命周期
- 创建(构造器or工厂方法)。前后可增强
- 依赖注入(@Autowired,@Resource,@Value)。前可增强
- 初始化(@PostConstruct)。前后可增强
- 销毁(@PreDestroy)。前可增强
向容器中注册Bean的后置处理器,用于解析@Autowired、@Value、@Resource、@PostConstruct、@PreDestroy等等,让他们起作用
向容器中注册BeanFactory的后置处理器,用于解析@ComponentScan、@Bean、@Import、@ImportResource、@MapperScanner等等
Aware接口及InitializingBean接口
初始化与销毁、Scope
AOP的实现方式
- 代理
- JDK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36public class JdkProxy {
interface Foo {
void foo();
}
static final class Target implements Foo {
public void foo() {
System.out.println("target foo");
}
}
// jdk 只能针对接口代理
public static void main(String[] param) throws IOException {
// 目标对象
Target target = new Target();
// 为什么需要类加载?正常流程:代码 -> 编译成字节码 -> 类加载
// 代理类是没有代码的
ClassLoader loader = JdkProxy.class.getClassLoader(); // 用来加载在运行期间动态生成的字节码
Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before...");
// 目标.方法(参数)
// 方法.invoke(目标, 参数);
Object result = method.invoke(target, args);
System.out.println("after....");
return result; // 让代理也返回目标方法执行的结果
}
});
System.out.println(proxy.getClass());
proxy.foo();
// 代理和target是兄弟关系
}
} - cglib
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28public class CglibProxy {
static class Target {
public void foo() {
System.out.println("target foo");
}
}
// 目标类不能是final的,因为不能继承,方法不能是final的,因为不能重写
// 代理是子类型, 目标是父类型
public static void main(String[] param) {
Target proxy = (Target) Enhancer.create(Target.class, new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
// Object result = method.invoke(target, args); // 用方法反射调用目标
// methodProxy 它可以避免反射调用
// Object result = methodProxy.invoke(target, args); // 内部没有用反射, 需要目标 (spring)
Object result = methodProxy.invokeSuper(o, args); // 内部没有用反射, 需要代理
System.out.println("after...");
return result;
}
});
proxy.foo();
}
}
- JDK
- AspectJ
- ajc编译器编译时修改字节码
- 类加载时修改字节码
- 代理