1.Spring
前置
第一个类
@Component
public class OrderService {
}
第二个类
@Component
public class UserService {
@Autowired
private OrderService orderService;
public void test(){
System.out.println(orderService);
}
}
配置文件
@ComponentScan("com.zhouyu")
public class AppConfig {
}
执行文件
public class Test {
public static void main(String[] args) {
// 入口
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService)applicationContext.getBean("userService");
userService.test();
}
}
1.依赖注入
正常的 UserService user = new UserService(),其中的orderService是没有没有值的,但是bean对象会调用以下方法,并赋值
for(Field field : userService.getClass().getDeclaredFields()){
// 存在Autowired注解
if (field.isAnnotationPresent(Autowired.class)){
field.set(userService, "");
}
}
流程
UserService --> 调用无参的构造方法 --> 对象 --> 依赖注入 --> bean对象
2.Map单例池
什么是一处创建多处使用?
UserService userService = (UserService)applicationContext.getBean("userService");
UserService userService1 = (UserService)applicationContext.getBean("userService");
UserService userService2 = (UserService)applicationContext.getBean("userService");
打印他们的结果,默认是单例的所以是同一个对象
流程
UserService --> 调用无参的构造方法 --> 对象 --> 依赖注入 --> 放入map的单例池 --> bean对象
单例池,对象类名首字母小写作为key,对象做value的map对象
3.初始化前postConstruct
// 如何在初始化bean的时候,给系统管理员bean赋值
private User admain;
@PostConstruct
private void setupAdmain(){
// mysql -->管理员信息 --> 初始化 admain --> admain
}
流程
UserService-->无参构造-->对象-->依赖注入(@Autowired)
-->初始化前(@PostConstruct)-->初始化-->初始化后
-->放入map单例池-->bean
4.初始化InitializingBean
@Component
public class UserService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// 初始化操作可以在这里做,比如前面的设置系统管理员
}
}
// Spring操作,如果对象实现了InitializingBean接口,就执行afterPropertiesSet方法
if(orderService instanceof InitializingBean) {
orderService.afterProertiesSet();
}
流程
UserService-->无参构造-->对象-->依赖注入(@Autowired)
-->初始化前(@PostConstruct)
-->初始化(InitializingBean)
5.Bean的初始化、Bean的实例化
实例化就是到创建对象,初始化就是后面设置值得部分
6.初始化后(aop)
UserService-->构造器-->普通对象-->依赖注入(Autowire)--> 初始化前(PostConstruct)
--> 初始化(InitialLizingBean)-->初始化后(aop) --> 代理对象 --> 放入map代理池
7.细讲构造器
// spring使用构造器规则
1.有无参构造器也有有参构造器,默认使用无参构造器
public UserService() {
}
public UserService(OrderService orderService) {
this.orderService = orderService;
}
2.只有一个有参构造器,就使用有参构造器
public UserService(OrderService orderService) {
this.orderService = orderService;
}
3.只有两个有参构造器,spring不知道使用哪个,会报错nosuchmethodexception,com.test.<init>(),<init>()表示无参的构造方法
public UserService(OrderService orderService) {
this.orderService = orderService;
}
public UserService(OrderService orderService,OrderService orderService1) {
this.orderService = orderService;
}
可以再构造器上面加上@Autowire选择一个
8.构造器之by Type,by Name
@Bean
public UserService(OrderService orderService) {
this.orderService = orderService;
}
@Bean
public UserService(OrderService orderService1) {
this.orderService = orderService;
}
@Bean
public UserService(OrderService orderService1) {
this.orderService = orderService;
}
现在单例池中就有了3个orderService实例,那么Spring怎么选择一个呢?
---先根据类型,再根据名称
aop原理
UserService类 ->推断构造器 ->普通对象
->依赖注入(@Autowire)
->初始化前(@PostConstruct)
->初始化(实现InitializingBean afterPropertiesSet)
->初始化后(aop)
->代理对象
->bean
实现aop步骤
1.开起aspect代理
@ComponentScan("com.zhouyu")
@EnableAspectJAutoProxy
public class AppConfig {
}
2.执行代理
@Aspect
@Component
public class ZhouyuAspect {
@Before("execution(public void com.zhouyu.service.UserService.test())")
public void zhouyuBefore(JoinPoint joinPoint) {
System.out.println("zhouyuBefore");
}
}
3.拿到代理对象
public static void main(String[] args) throws IllegalAccessException {
// 入口
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService)applicationContext.getBean("userService");
userService.test();
}
其实这时候只要从map单例池中取到的UserService对象,就是代理对象
4.原理
Class UserServiceProxy extents UserSevice{
UserService target = 普通对象;
public void test(){
//before方法
target.test();
}
}
1.Spring会生成一个代理对象,继承于UserService,声明target等于普通对象
2.实际用户getBean拿到的是代理对象
3.代理对象执行test方法的步骤是切片方法中先执行before,然后普通对象执行test方法
Spring事务底层原理
为什么事务会失效
1.使用事务,先加上@Configuration
@Transactional
public void test(){
System.out.println(orderService);
a(); //a方法的事务失效了,因为这里普通对象执行a方法
}
@Transactional(propagation = Propagation.NEVER)
public void a(){
System.out.println(orderService);
}
原理
Class UserServiceProxy extents UserSevice{
UserService target = 普通对象;
public void test(){
//遍历@Transactional注解,事务管理器新建一个数据库连接
connection.autoCommit = false;
target.test();普通对象执行test
connection.commit 或 connection.rollback
}
}
2.若想让a方法用到事务,解决方法有两个
①新建一个newBean,autowire导入后,用newBean.a(),这里newBean就是一个代理对象
②直接autowire一个当前对象UserService,调用方法变为userService.a(),这里要注意循环依赖问题
Spring使用3级缓存来解决循环依赖
AService
1.AService -> 创建普通对象放入singletonFactories<aService,lambda>里面包含普通对象和beandefinition)
2.autoWire BService ->执行创建BService
BService
3.BService -> 创建普通对象
4.autoWire AService -> 去单例池SingletonObjects中找AService(没有找到)->在CreatSet中找到了,说明AService正在创建(证明循环依赖)
-> earlySingletonObjects(没有找到)
-> 通过singletonFactories判断是否要aop得到AService代理对象或者普通对象
-> 放入earlySingletonObjects
5.BService创建完成
AService继续
6.AService bean创建完成,将AService放入单例池
第一层 singletonObjects 单例池
第二层 earlySingletonObjects 存放临时的代理对象或者普通对象,这时对象都还没有创建完全
第三层 singletonFactories 存放lambda表达式(对象名称,普通对象,beandefinition)