Java spring 01 (图灵)

用来讲解的例子:在main函数中创建spring容器

用AnnotationConfigApplicationContext创建一个spring容器

	// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) applicationContext.getBean("userService");
		
		userService.test();

配置类AppConfig :这里是AnnotationConfigApplicationContext扫描的类,主要是用来添加项目的一些信息

@ComponentScan("com.zhouyu")

public class AppConfig {
}

其中这个例子用到的对象bean:

UserService 对象:

@Component
public class UserService {

	@Autowired
	private OrderService orderService;

	public void test(){
		System.out.println(orderService);
	}

}

OrderService 对象:

@Component
public class OrderService {

}

01.属于spring特性,依赖注入:

依赖注入 @Autowird

例子:UserService 类中有属性orderService,被 @Autowird修饰

	@Component
public class UserService {

	@Autowired
	private OrderService orderService;

	public void test(){
		System.out.println(orderService);
	}
}

测试:

两种UserService 类的对象实例化,前一种是用spring来创建的,后一种是new创建的

UserService userService1 = (UserService) applicationContext.getBean("userService");


UserService userService2= new UserService ();

spring依赖注入的原理:

//利用class的反射,获取class对象中的全部属性
for (Field field : userService1.getClass().getDeclaredFields()) {
//在获取的属性中去判断是不是有autowired的注解,有的话,就会执行属性赋值的操作,这也就是依赖注入
 			if (field.isAnnotationPresent(Autowired.class)) {
 			field.set(userService1, ??);
 			}
 		}

结果:

由spring创建的bean,属性orderService有值
new 出来的对象 属性orderService没有值

02.spring创建自动对象,一般用类的无参构造方法。在这里插入图片描述

讨论在spring创建类的实例的时候,会调用到类的什么构造函数:

Spring的判断逻辑如下:

  1. 如果一个类只存在一个构造方法,不管该构造方法是无参构造方法,还是有参构造
    方法,Spring都会用这个构造方法(有参的构造函数,参数要在spring容器中去按照参数类型来找,如果同一个类型存在多个bean对象的话,在按照参数的名字取去找)
  2. 如果一个类存在多个构造方法
    a. 这些构造方法中,存在一个无参的构造方法,那么Spring就会用
    这个无参的构造方法
    b. 这些构造方法中,不存在一个无参的构造方法,那么Spring就会
    报错

例子:
此时userservice类只有一个有参的构造函数,参数类型是OrderService 参数名是orderService123
在这里插入图片描述

在配置类AppConfig中,同时创建两个UserService的bean,
此时,由于@Component 和@Bean ,一共是有三个UserService 的bean的

@Component
public class UserService {

	 private OrderService orderService;
	
	 public UserService(OrderService orderService123){
	 
		 this.orderService=orderService123;
		 System.out.println("2");
	 
	
	}

}

@ComponentScan("com.zhouyu")

public class AppConfig {

@Bean
 	public UserService userService1 () {
 		return new UserService ();
 	}
@Bean
 	public UserService userService2 () {
 		return new UserService ();
 	}
}

测试:此时spring容器中已经有三个OrderService类型的对象了
在这里插入图片描述

一.如果 UserService 类的那个有参构造函数 的参数 类型 OrderService 并没有被spring创建bean对象的话,也就是一个普通类的话(没有被@Component 修饰的话),报错

二.如果spring之前已经把这个类型实例化对象了,就会去spring容器内取找,查找的顺序是,先按照参数类型来找,如果满足的bean数量超过一个的话,而后根据参数名字来找,如果都找不到的话,就会报错

在这里插入图片描述

三.但是如果去掉配置类中的两个@bean的话,只留下@Component OrderService的话,此时spring容器只剩下一个bean ,无论构造函数中的OrderService参数名叫什么,都可以成功把参数赋值到这个spring创建的bean

四.如果执意要指定那个构造函数是spring默认的用来自动创建bean的,添加@Autowired到构造函数上
在这里插入图片描述

03.spring把类依赖注入后,开始初始化

初始化有三个阶段:
初始化前,初始化,初始化后
在这里插入图片描述
初始化前一般调用 @PostConstruct 修饰的方法

例子:UserService类
其中有被 @PostConstruct修饰的方法a

@Component
public class UserService {

	@Autowired
	private OrderService orderService;

	public void test(){
		System.out.println(orderService);
	}
	
	@PostConstruct
    public void a(){
	   System.out.println("这个是初始化前的操作");
    }


}

测试:
在用getBean来实例化UserService的bean对象的时候,用在显示台输出内容:这个是初始化前的操作

// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) applicationContext.getBean("userService");
		
		userService.test();

原理

//是在实例化的过程中,用Class类的反射的机制,来获取类的全部方法
for (Method method : userService1.getClass().getDeclaredMethods()) {
//在获取的方法中去判断是不是有注解PostConstruct,有的话,会被唤醒(这里是JDK的动态代理method.invoke  是用于执行method的方法)
 			if (method.isAnnotationPresent(PostConstruct.class)) {
 				method.invoke(userService1, null);
 			}
 		}

04 初始化

初始化,是实现一个接口 InitializingBean
在这里插入图片描述
在实现这个接口的过程中,会重写afterPropertiesSet方法,这个方法就会在初始化的这个阶段来执行,就像上文中写的那样被@PostContruct 修饰的方法,会在初始化前被调用

在这里插入图片描述


@Component
public class UserService implements  InitializingBean{

	@Autowired
	private OrderService orderService;

	public void test(){
		System.out.println(orderService);
	}

	@PostConstruct
    public void a(){
	   System.out.println("这个是初始化前的操作");
    }
    
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("这个是初始化的操作");
	}

}

执行这个afterPropertiesSet方法的原理:

用instanceof 方法 判断是不是实现了接口InitializingBean,如果是的,就会调用afterPropertiesSet

在这里插入图片描述

InitializingBean接口的详细情况:
在这里插入图片描述
InitializingBean接口源码中的情况:

在这里插入图片描述
invokeInitMethods方法会判断是不是实施了接口InitializingBean,
如果有,调用重写的方法afterPropertiesSet:在这里插入图片描述

在这里插入图片描述

05.初始化后,这里是spring的AOP的操作地点
在这里插入图片描述

AOP的原理:
在这里插入图片描述
在这里插入图片描述
配置类要添加一个注解

@ComponentScan("com.zhouyu")
@EnableAspectAutoProxy

public class AppConfig {


}

创建一个切面类:这里面定义的是在哪里去插入切面逻辑

@Aspect
@Component
public class ZhouyuAspect {
//切入点:userservice的test方法
	@Pointcut("execution(public void com.zhouyu.service.UserService.test())")
	public void a(){

	}

	@Before("a()")
	public void zhouyuBefore(JoinPoint joinPoint) {
		System.out.println("zhouyuBefore");
	}


}

被切入的类的代码

@Component
public class UserService {

	@Autowired
	private OrderService orderService;

	public void test(){
		System.out.println(orderService);
	}




}

此时,运行到切入点的时候(也就是UserService类的test方法),UserService类的对象会变成一个代理类对象在这里插入图片描述

但是要注意的是:
此时这个代理对象的属性OrderService是空的
在这里插入图片描述

原理是:AOP生成代理类对象的时候,并没有进行依赖注入,也就没有属性值
在这里插入图片描述

但是运行到这个test方法时候,断点会跳转到UserServicenei进去去看,这个时候,属性OrderService是有值的在这里插入图片描述
原理:
1.cjlib会生成一个代理类,这个代理类会继承被代理对象类,这里的target会被赋值给被代理类的对象,也就是切入点所在的类的对象(此时,这个对象应该是spring中创建的bean)
2.并产生一个对象(代理类实例)
3. 这个实例会执行代理类的方法(也就是增添切面逻辑的test方法)
在这里插入图片描述

增添切面逻辑的test方法
在这里插入图片描述

查看效果:此时的代理类的target属性:

在这里插入图片描述

这个一个例子:如何判断当前Bean对象需不需要进行AOP:

找出所有的切面Bean
遍历切面中的每个方法,看是否写了@Before、@After等注解
如果写了,则判断所对应的Pointcut是否和当前Bean对象的类是否匹配
如果匹配则表示当前Bean对象有匹配的的Pointcut,表示需要进行AOP

08.数据库的事务

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
这里两个方法用到了datasource方法,不是bean这样的使用,没有autowird 会创建两个datasource

@configuration 会运行代理模式 会产生一个AppConfig的代理对象
这个代理对象会在spring的容器先找bean,datasource此时已经创建了bean对象,这个bean对象 会自动注入 那两个
在这里插入图片描述
在这里插入图片描述
09.spring事务管理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值