package com.example.demospring1; import com.example.demospring1.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import java.lang.reflect.Field; /** * @description: * @author: 范子祺 **/ public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService)context.getBean("userService"); //测试2 依赖注入 userService.test(); //结果2 orderService seecom.example.demospring1.service.OrderService@1e67a849 //测试1 默认都是单例bean // UserService userService1 = (UserService)context.getBean("userService"); // UserService userService2 = (UserService)context.getBean("userService"); // System.out.println(userService); // System.out.println(userService1); // System.out.println(userService2); //结果1 // com.example.demospring1.service.UserService@1e67a849 // com.example.demospring1.service.UserService@1e67a849 // com.example.demospring1.service.UserService@1e67a849 // UserService userService3 = new UserService(); // context.getBeanFactory().registerSingleton("xxx",userService3); // UserService userService1 = new UserService(); // // for (Field field: userService1.getClass().getDeclaredFields()){ // if (field.isAnnotationPresent(Autowired.class)){ // field.set(userService1,??); // } // } } }
@ComponentScan("com.example.demospring1") public class AppConfig { } @Component public class UserService { @Autowired private OrderService orderService; public void test(){ System.out.println("orderService see"+orderService); } } @Component public class OrderService { }
1 依赖注入,2 单例bean,
userservice类->无参构造函数->对象->依赖注入->初始化->放入Map单例池->bean对象
希望使用类的时候,它里面的某个属性,已经从数据库中取到值了
userservice中增加
@PostConstruct public void a(){ System.out.println("初始化前"); }
结果
14:24:27.525 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService'
初始化前
orderService seecom.example.demospring1.service.OrderService@75f9eccc
继续增加
public class UserService implements InitializingBean { @PostConstruct public void a(){ System.out.println("初始化前-PostConstruct"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("初始化前-afterPropertiesSet"); } 结果 14:28:19.050 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService' 初始化前-PostConstruct 初始化前-afterPropertiesSet orderService see:com.example.demospring1.service.OrderService@5d47c63f
构造函数的证明
类UserService 增加 public UserService() { System.out.println("空参构造函数:"+orderService); } public UserService(OrderService orderService) { this.orderService = orderService; System.out.println("1个入参orderService构造函数:"+orderService); } 结果 空参构造函数:null 初始化前-PostConstruct 初始化前-afterPropertiesSet orderService see:com.example.demospring1.service.OrderService@5d47c63f
自动选择了无参构造函数
OrderService 增加 public OrderService() { System.out.println("空参OrderService"+this); } UserService 修改 // public UserService() { // System.out.println("空参构造函数:"+orderService); // } public UserService(OrderService orderService) { this.orderService = orderService; System.out.println("1个入参的UserService构造函数:"+orderService); } 结果 17:49:18.193 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService' 空参OrderServicecom.example.demospring1.service.OrderService@1445d7f 17:49:18.198 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService' 17:49:18.365 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'userService' via
constructor to bean named 'orderService' 1个入参的UserService构造函数:com.example.demospring1.service.OrderService@1445d7f 初始化前-PostConstruct 初始化前-afterPropertiesSet orderService see:com.example.demospring1.service.OrderService@1445d7f
1 依赖注入, 2 单例bean
UserService增加 public UserService(OrderService orderService1,OrderService orderService2) { this.orderService = orderService; System.out.println("2个入参的UserService构造函数:"+orderService); System.out.println("2个入参的UserService构造函数h2:"+orderService1+"="+orderService2); } 结果 17:53:44.235 [main] WARN org.springframework.context.annotation.AnnotationConfigApplicationContext -
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.
BeanCreationException: Error creating bean with name 'userService' defined in file [/Users/shenshaonian/Desktop/selfPro/spr
ing/demoSpring1/target/classes/com/example/demospring1/service/UserService.class]: Instantiation of bean failed; nested exc
eption is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demospring1.service.U
serService]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.example.demospring1.service.UserService.<init>()
多个有参的构造函数,无法判断使用哪个构造函数创建对象
UserService 修改 // public UserService(OrderService orderService) { // this.orderService = orderService; // System.out.println("1个入参的UserService构造函数:"+orderService); // } public UserService(OrderService orderService1,OrderService orderService2) { this.orderService = orderService; System.out.println("2个入参的UserService构造函数:"+orderService); System.out.println("2个入参的UserService构造函数h2:"+orderService1+"="+orderService2); } public void test(){ orderService.orderServicePrint(); System.out.println("userservice look orderService see:"+orderService+"=="); } OrderService 增加 public void orderServicePrint(){ System.out.println("orderServicePrint look"); } 结果空参 OrderServicecom.example.demospring1.service.OrderService@1445d7f 18:01:15.133 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService' 18:01:15.236 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'userService' via constructor to bean named 'orderService' 2个入参的UserService构造函数:null 2个入参的UserService构造函数h2:com.example.demospring1.service.OrderService@1445d7f=com.example.demospring1.service.OrderService@1445d7f 初始化前-PostConstruct 初始化前-afterPropertiesSet orderServicePrint look userservice look orderService see:com.example.demospring1.service.OrderService@1445d7f==
1 autowire注释的bean一般会在对象使用的时候才会实例化,2 对象放到构造函数的参数中也是一种提前的实例化, 最终orderservice的地址都是
1445d7f, 这里面是通过cglib代理实现的, cglib是啥, asm是啥, 这里我有点搞不清了。 可能有错误的地方。
修改 UserService @Autowired public UserService(OrderService orderService1,OrderService orderService2) { this.orderService = orderService; System.out.println("2个入参的UserService构造函数orderService="+orderService); System.out.println("2个入参的UserService构造函数orderService1="+orderService1+"orderService2="+orderService2); } 增加 AppConfig @Bean public OrderService orderService1(){ return new OrderService(); } @Bean public OrderService orderService2(){ return new OrderService(); } 增加 Test OrderService orderService = (OrderService)context.getBean("orderService"); OrderService orderService1 = (OrderService)context.getBean("orderService1"); OrderService orderService2 = (OrderService)context.getBean("orderService2"); System.out.println("test orderService:"+orderService); System.out.println("test orderService1:"+orderService1); System.out.println("test orderService2:"+orderService2); 结果 21:59:32.974 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService' 空参OrderServicecom.example.demospring1.service.OrderService@7bc1a03d 21:59:32.975 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService' 21:59:33.142 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService1' 空参OrderServicecom.example.demospring1.service.OrderService@18a70f16 21:59:33.175 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService2' 空参OrderServicecom.example.demospring1.service.OrderService@c8e4bb0 21:59:33.183 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'userService' via constructor to bean named 'orderService1' 21:59:33.184 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'userService' via constructor to bean named 'orderService2' 2个入参的UserService构造函数orderService=null 2个入参的UserService构造函数orderService1=com.example.demospring1.service.OrderService@18a70f16orderService2=com.example.demospring1.service.OrderService@c8e4bb0 初始化前-PostConstruct 初始化前-afterPropertiesSet orderServicePrint look userservice look orderService see:com.example.demospring1.service.OrderService@7bc1a03d== test orderService:com.example.demospring1.service.OrderService@7bc1a03d test orderService1:com.example.demospring1.service.OrderService@18a70f16 test orderService2:com.example.demospring1.service.OrderService@c8e4bb0
OrderService@7bc1a03d
OrderService@18a70f16 orderservice1
OrderService@c8e4bb0 orderservice2
这里是实例化了三个orderservice的bean ,可以推断出,spring是bytype + byname的
证明确实bynam了
证明使用了byname
再次根据我们上面没有在appconfig中注入bean的时候,我们的orderservice打出来的地址是一样的,说明, class的类型只有一个bean的时候,是直接取bytype判断的,和bean的name
无关
所以单例模式,单例bean,根本就是在讲目的不同的两件事
aspect
结合下面的代码看, 1 orderservice还没初始化,2 aop使用的是cglib
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService)context.getBean("userService"); userService.test(); @ComponentScan("com.example.demospring1") @EnableAspectJAutoProxy public class AppConfig { @Component public class UserService implements InitializingBean { @Autowired private OrderService orderService; @PostConstruct public void a(){ System.out.println("初始化前-PostConstruct"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("初始化前-afterPropertiesSet"); } public void test(){ //orderService.orderServicePrint(); System.out.println("userservice look orderService see:"+orderService+"=="); } @Component public class OrderService { public OrderService() { System.out.println("空参OrderService"+this); } public void orderServicePrint(){ System.out.println("orderServicePrint look"); } } @Aspect @Component public class TestAspect { @Before("execution(public void com.example.demospring1.service.UserService.test())") public void testUserBefore(JoinPoint joinPoint){ System.out.println("class: TestAspect"+"method: testUserBefore"); } }
userservice类->推断构造函数->普通对象->依赖注入->初始化前(postconstruct)->初始化(initializingBean)->初始化后(aop)->代理对象->放入Map单例池->bean对象
重新断点, 摆出问题:
外面两个orderservice, 到里面的orderservice
cglib 是基于父子类的
推测一 伪代码
super.test()的问题这里没有讲透。 视频里面想说的应该是,第一层我们看见的代理对象userservice有值,但是里面的orderservice无值, 而实际上我们调用进去的时候,发现orderservcie又有值了。
代理对象找到真的userservice对象,调用test,test里面使用到了orderservice, 而真正实例化的两个类没有到管理bean的map中, 是通过代理对象钩子的方式唤起真正的对象去做事情。就好像生活中,张三找王五去买一头牛一样,张三买牛,王五卖牛,这个时候大多数我们都要经过一次市场,假设我们通过市场的刘麻子买牛, 这个时候刘麻子知道谁卖牛,于是刘麻子就让张三去找王五买牛。凡是要买牛卖牛的大家都可以来找刘麻子。
com.example.demospring1.service.UserService@33aeca0b 代理对象userserviceProxy
普通对象userservice是 2749 普通对象orderservice是2750
纯纯的中介思想哈哈哈哈哈
spring的事务
代码
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService)context.getBean("userService"); userService.test(); @ComponentScan("com.example.demospring1") //@EnableAspectJAutoProxy @EnableTransactionManagement @Configuration // 自动帮我们把下面几个的关系装配好, 描述不完全准确,你可以自己去掉这个看一下报错 public class AppConfig { @Bean public JdbcTemplate jdbcTemplate(){ return new JdbcTemplate(dataSource()); } @Bean public PlatformTransactionManager transactionManager(){ DataSourceTransactionManager manager = new DataSourceTransactionManager(); manager.setDataSource(dataSource()); return manager; } @Bean public DataSource dataSource(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/demo?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useSSL=false"); dataSource.setUsername("root"); dataSource.setPassword("1234qwer"); return dataSource; } @Component public class UserService { @Autowired private JdbcTemplate jdbctemplate; @Autowired UserService userService; @Transactional public void test(){ jdbctemplate.execute("insert into user(name,age,sex, addr) values('测试3',100,1,'测试地址')"); userService.a();
//a();
// throw new NullPointerException(); } ///继续学习其他的 spring的事务和相关的面试题 @Transactional(propagation = P
//ropagation.NEVER) public void a(){ jdbctemplate.execute("insert into user(name,age,sex, addr) values('测试2',100,1,'测试地址')"); // throw new NullPointerException(); }
结果
Exception in thread "main" org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
注意:
userService.a();
//a();
注意:上面这个两个方法, userService调用的时候是失败的,never生效了, 而a()调用是成功的。 原因是:userService掉用的时候,实际是代理对象去掉的, 而trans的注解, aop思想切的所关注的也是这个代理对象。
普通对象,切面方法是没有关注他的。 我们可以通俗的理解为, 加了事务注解,这个时候,事务实际上关注的是你这个代理人, 你这个代理如果之前启用过事务了, 后面这个代理再启用事务的时候,发现有个never,那这个时候监控到了,直接抛错,
而普通对象,别人跟你没得关系,不监控你。
同理想让它事务生效, 拆个新类,调用测试,一样的生效。