你确定真的了解 Java 四种引用(强引用、弱引用、软引用、虚引用)了吗?
SpringBoot四种读取properties文件的方式
@PropertySource
springboot读取自定义properties配置文件方法
spring-boot-configuration-processor 是干啥用的
ioc 反转控制 就是将我们创建对象的方式反转了 以前对象的创建时由开发人员自己维护 包括依赖关系也是自己注入 学习spring之后 对象的创建以及依赖关系可以由spring完成创建和注入 反转控制也就是反转了对象的创建方式 从人们自己到由spring自己进行
//获得容器
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//从容器中获取对象
IService service = (IService) ac.getBean("service");
di 比IOC概念要小一些 Dependency Injection 依赖注入
实现IOC思想 DI做支持。
<bean id="hello" class="com.neu.service.HelloSpring">
<property name="who">
<value>Springvalue>
property>
bean>
<bean id="mySchool" class="com.neu.service.School">
<constructor-arg name="name" value="肇庆学院"/>
bean>
注意:要保证赋值顺序要与构造器中的参数顺序一致。
在实际应用里,随着应用规模的增加,系统 Bean 数量也大量增加,导致配置文件变得
非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可
以将 Spring 配置文件分解成多个配置文件。
1)平等关系的配置文件
2)包含关系的配置文件
各配置文件中有一个总文件,总配置文件将各其它子文件通过引入,在 java 代
码中只需要使用总配置文件对容器进行初始化即可。
注:2,3,4与1等效是为了以后对其精心功能上的扩展使它们不再等效。
使用内置服务器启动springboot项目时,会从@SpringBootApplication修饰类所在的包开始,加载当前包和所有子包下的类,将由
@Component 、@Repository、@Service、@Controller修饰的类交由spring进行管理。
①、singleton:单例模式,在整个 Spring 容器中,使用 singleton 定义的 Bean 将是单例的,只有一个实例,默认为单例。
②、prototype:原型模式,即每次使用 getBean 方法获取的同一个的实例都一个新的实例。
③、request:对于每次 Http 请求,都会产生一个不同的 Bean 实例,表示在一次http请求内有效(只适用于web应用)。
④、session:对于每个不同的 http session,都会产生一个不同的 bean 的实例,表示在一个用户会话内有效(只适用于web应用)。
⑤、globalSession表示在全局会话内有效(只适用于web应用)。
注意:
1)对于 scope 的值 request、session 与globalSession,只有在 web 应用中使用Spring 时,才起作用。
2)对于 singleton,该 bean 是在容器被创建时即被装配好了。
3)对于prototype,bean 实例是在代码中使用该 bean 实例时才进行装配,也就是懒加载。
需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。
**使用该注解完成属性注入时,类中无需 setter()方法。
@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter()方法上。
Spring中@Resource与@Autowired、@Qualifier的用法与区别
默认是按照类型装配注入的,如果想按照名称来装配注入,则需要结合@Qualifier一起使用;
注意:
按照类型装配注入有一种出错的情况,如果这个类有多个实现类,那么spring就不知道找那个类了。
上述的情况就必须结合@Qualifier一起用了。
如果@Autowired和@Qualifier同时用了,那么会先按类型装配,找不到才按名称装配
这个注解是属于spring的,
默认情况下必须要求依赖对象必须存在,不然直接报错,如果要允许null 值,可以设置它的required属性为false,
如:@Autowired(required=false)
@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入,
名称可以通过name属性进行指定。
这个注解属于J2EE的,Sping 只是提供了 JSR-250 规范中定义@Resource 标准注解的支持。
如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。
当找不到与名称匹配的bean时才按照类型进行装配。
但是需要注意的是,name属性一旦指定,就只会按照名称进行装配。
Spring AOP动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
spring-aop原理讲解 JDK动态代理和CGLIB动态代理
摘抄:
Spring AOP动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
- JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和
Proxy 类。- 如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码
生成的类库,可以在运行时动态的生成某个类的子类(通过修改字节码来实现代理)。
注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
jdk和cglib动态代理是共同用来实现我们的aop面向切面的功能。
AOP 就是纵向的编程,如业务 1 和业务 2 都需要一个共同的操作,与其往每个业务中
都添加同样的代码,不如写一遍代码,让两个业务共同使用这段代码。在日常有订单管
理、商品管理、资金管理、库存管理等业务,都会需要到类似日志记录、事务控制、权限
控制、性能统计、异常处理及事务处理等。AOP 把所有共有代码全部抽取出来,放置到某
个地方集中管理,然后在具体运行时,再由容器动态织入这些共有代码。
AOP实现的底层原理
只有发生在运行期,则可直接通过 Java 语言的反射机制与动态代理机制来动态实现。
定义前置通知,需要实现 MethodBeforeAdvice 接口,访接口中有一个方法 before(),在目
标方法执行之前执行,前置通知的特点:
(1)在目标方法执行之前先执行
(2)不改变目标方法的执行流程,前置通知代码不能阻止目标方法执行
(3)不改变目标方法执行的结果
定义后置通知,需要实现接口 AfterReturningAdvice,该接口中有一个方法 afterReturning()
会在目标方法执行之后执行。后置通知的特点:
(1)在目标方法执行后执行
(2)不改变目标方法的执行流程,后置通知代码不能阻止目标方法执行
(3)不改变目标方法执行的结果
定义环绕通知,需要实现接口 MethodInterceptor,环绕通知,也叫方法拦截器,可以在目
标方法调用之前及之后做处处理,可以改变目标方法的返回值,也可以改变程序执行流
程。
注意:org.aopalliance.intercept.MethodInterceptor 才是需要的包。
其中最终通知是指无论程序执行是否正常,该通知都会执行。
对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一。AspectJ 也实现了
AOP 的功能,且实现方式更为简捷,使用更为方便,而且还支持注解式开发。在 Spring 中
使用 AOP 开发时,一般使用 AspectJ 的实现方式。
1、AspectJ 简介
AspectJ 是一个面向切面的框架,它扩展了 Java 语言。AspectJ 定义了 AOP 语法,所以它有
一个专门的编译器用来生成遵守 Java 字节编码规范的 Class 文件。
2、AsectJ 的通知类型
常用的有五种类型:
1)前置通知
2)后置通知
3)环绕通知
4)异常通知
5)最终通知
其中最终通知是指无论程序执行是否正常,该通知都会执行。
3、AspectJ 的切入点表达式
4. AspectJ 基于注解的 AOP 实现
1)实现步骤
Step1:定义业务接口与实现类
Step2:定义切面 POJO 类
Step3:在切面类上添加**@Aspect** 注解,指定当前 POJO 类将作为切面
Step4:在 POJO 类的普通方法上添加通知注解
Step5:注册目标对象与 POJO 切面类
Step6:注册 AspectJ 的自动代理
Step7:测试类中使用目标对象的 id
2)@Before 前置通知-方法有 JoinPoint 参数
3)@AfterReturning 后置通知-注解有 retruning 属性
4)@Around 环绕通知-增加方法有 ProceeDingJoinPoint 参数
5)@AfterThrowing 异常通知-注解中有 throwing 属性
6)@After 最终通知
7)@Pointcut 定义切入点
整个表达式可以分为五个部分:
1、execution(): 表达式主体。
2、第一个*号:表示返回类型, 号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,
com.sample.service.impl 包、子孙包下所有类的方法。
4、第二个号:表示类名,号表示所有的类。
5、(…):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,
两个句点表示任何参数
AspectJ 对 AOP 的实现有两种方式
1)注解方式
号:表示返回类型, 号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,
com.sample.service.impl 包、子孙包下所有类的方法。
4、第二个号:表示类名,号表示所有的类。
5、(…):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,
两个句点表示任何参数
AspectJ 对 AOP 的实现有两种方式
1)注解方式
2)XML 方式
为什么它可以生成dao接口对应实现类?
就是因为它使用的设计模式中的代理模式,其中的动态代理。
它通过你的映射关系对DAO接口进行增强,自动生成了其实现类。
其实mybatis用的也是这个原理,不过它对代码操作的自由度高,也就是有一半映射你得自己写,写好关系mapper文件,再匹配你指定的dao接口,它才帮你做动态代理,这就是半ORM。
吐槽:其实感觉jpa还是挺厉害的,你说自由度嘛,其实也没比mybatis差多少,国外用的最多的就是JPA了,感觉国内太迷信mybatis了。
具体可看这个链接:设计模式—代理模式
spring-data-jpa的@Repository扫描原理
JDK动态代理实现原理
Java两种动态代理JDK动态代理和CGLIB动态代理
还有就是spring-data-jpa的代理类,已经写了@Repository注解了,所以jpa在给相应的dao做增强(也就是生成实现类)的时候,因为有@Repository的原因,所以就直接纳入spring管理了,就像普通的实现类一样。
Class的toString()方法。
Object在Class类之前,那是在编译期;Class能表示Object类,那是在JVM中。
Class只是一个用于描述Java类与接口的、用于支持反射操作的类型。
Java基础之—反射(非常重要)
spring 中使用反射
Spring注入的反射解释
tips:其实spring的配置文件和springMVC的配置文件起什么名字都可以的,因为,spring的web应用是基于servlet技术进行开发的,
而servlet技术又有核心配置文件web.xml(servlet是用它来方便web工程的开发的),
所以,这两个文件最终都是要写到web.xml去注册的,然后spring才开始运作起来的。
Spring注解中@Configuration和@Configurable的区别
Spring系列——@lazy注解
Spring注解——使用@ComponentScan自动扫描组件
@Primary 和 @Qualifier