栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring零散知识(未完成还在补充)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring零散知识(未完成还在补充)

对于一些积累的问题总结

Bean是线程安全的吗

不是,spring不保证bean线程安全,bean就是一个对象,关键是我们里面的代码写的是不是线程安全的

异步线程注解失效,和Spring事务注解失效

他俩是一个原因,放在一块说,原因就是用的不是SpringAOP过的对象方法

要自己注入自己,然后用注入的对象的异步方法才对

我实习遇到过这个问题

解决方式有两种,就是自己注入自己然后然后用注入的对象的异步方法,或者写在别的类里面。我的代码它就写在这个类里合适,所以建议用第一种方法。

Bean的创建流程

从容器启动开始:

1、 Spring启动首先扫描注解把扫描到的信息封装成BeanDefinition

2、 推断构造方法用反射创建单例Bean

3、 Bean的属性注入

5、 做接口的回调

4、 执行自定义的初始化方法给属性赋值,实现InitializingBean接口afterPropertiesSet方法或者用@PostConstruct注解标注在初始化方法上。

6、 最后一步做AOP,如果做AOP的话单例池放的就是代理对象,即包裹了一层。

补充细节:

扫描注解,注解会表示一些信息,比如单例模式原型懒加载等

在实例化对象的时候会选择一个合适的构造方法具体为:1、如果有有参的和无参的默认用无参的。2、当只有一个构造方法的时候就用这个。3、如果没有默认构造方法有很多非默认构造方法会报错,Spring不知道我们想用哪个,我们可以在想用的构造方法上加@Autowired注解。

@Component
public class MyClass{
    
    Student student;

    //会先ByType在ByName (ByName根据属性名字找,找不到就报错)
    public UserService (Student student){
        this.student = student;
    }


}

Bean的属性注入是Bean也需要注入Bean,Bean之间有依赖关系的情况

接口回调用,会注入一些东西比如:

自定义初始化方法比如:我们其中一个属性需要查询数据库来得到,那就执行查询数据在赋值的逻辑。

补充:后置处理是Spring技术概念的统称。

Spring循环依赖

在Spring里Bean有自己的创建过程,如果只有一级缓存,就找不到半成品的Bean。

在Java代码里(没用框架)如果如果a对象依赖b对象,b反过来又依赖a,或者又出现了c,都很好解决如下:

class A{
    B b;
    void setB(B b) {
        this.b = b;
    }

}
class B{
    A a;
   void setA(A a) {
        this.a = a;
    }

}
public static void main(String[] args) {
    A a = new A();
    B b = new B();
    
    //直接就能set
    a.setB(b);
    b.setA(a);     
}

Spring框架里这样就会产生循环依赖如下:

@Component
public class A {
    // A中注入了B
	@Autowired
	private B b;
}

@Component
public class B {
    // B中也注入了A
	@Autowired
	private A a;
}
//这样A和B就循环依赖了

解释:

因为在上个问题Bean的创建流程中,如果BeanA的属性也要注入另一个BeanB但是BeanB不在容器里,就会出走创建BeanB的流程,创建BeanB的属性要注入BeanA,但是BeanA还没创建完成,容器里找不到BeanA,又来创建BeanA,循环往复。

解决:

Spring用了三级缓存来解决循环依赖。如果不用AOP的话,二级缓存就能解决,但是如果AOP的话要三级缓存解决循环依赖。

一级是HashMap放创建好的Bean。二级是HashMap放创建Bean的半成品。三级是ConcurrentHashMap,用Lambda表达式把结果直接放进二级缓存。

这时候创建Bean注入属性的时候不会先去一级缓存去找,而是去二级缓存找是否有半成品,这样才用提前暴露引用的方式,在上述BeanB注入BeanA得时候就能在二级缓存找到半成品引用啦。

但是单例Bean不能用多级缓存解决构造方法循环依赖,因为构造方法在创建对象Bean的推断构造方法里那部放,还没放进缓存中呢。

@Autowired和@Resource属性注入时候注意

@Autowired:先ByType在ByName

1、先看容器里这Type个数一个就直接用,多个继续筛选。

2、再筛选掉Bean属性候选者=false的Bean。

3、再筛掉不符合@Qualifier的组,@Qualifier注解用在注册Bean的方法上又给Bean分了组名,@Autowired注入的地方结合@Qualifier找Bean的别名组。

4、再筛选根据@Primary找每个类型里的主Bean。

5、如果没写@Primary,再取优先级最高的Bean,@Priority(1)、@Priority(2)值小优先级高。

6、如果@Primary和@Priority()都没写,根据Name属性名字看是否存在,不存在就报错。

//注册Bean有个候选者属性默认是true
//方法的名字是Bean的名字
@Bean (autowireCandidate = false)
public Student student1(){
    return new Student():
}

@Bean (autowireCandidate = true)
@Qualifie("别名组1")
public Student student2(){
    return new Student():
}

//@Primary同一个类型只能标注一个主Bean
@Bean
@Qualifie("别名组1")
@Primary
public Student student3(){
    return new Student():
}

//@Priority(1)值小优先级高
@Bean
@Priority(1)
public Student student4(){
    return new Student():
}

@Bean
@Priority(2)
public Student student5(){
    return new Student():
}
class MyClass{

    @Autowired
    @QualiQualifier("别名")
    Student student123;

}

@Resource:先ByName在ByType

@Resource是Java提供的,Spring实现了它

1、@Resource有个name属性如果指定了,直接按name属性去找,找到就找到,找不到就报错。

2、如果没有指定name,那就根据属性的名字看容器里能否找到

3、找不到在看Type个数一个就找到,多个就报错

class MyClass{

    @Resource(name = "student1")
    Student student3;

    @Resource
    Student student123;

}

Spring的AOP实现

Spring的AOP是干嘛的:他是用来增强方法的方法前后插入我们的增强逻辑,

像是事务,日志,都是用AOP做的

代码怎么写AOP:

@Aspect //表示写的是一个切面类
@Component //当没有明确语义是用Component注册
public class MyAspect{
    
    //定义一个切点//里面写表达式
    @Pointcut("execution(com.service.Buy.play(..))")
    public void AspectPoint() {}

    
    //下面是5种通知
    //before是前置 (里面写切点方法)
    @Before ("AspectPoint()")
    public void MyBefore() { System.out.println("这是前置逻辑");}

    //后置
    @After("切点方法")

    //环绕就是前后
    @Around("切点方法")

    //在目标方法返回结果后调用
    @AfterReturning("切点方法")

    //在目标方法抛出异常后调用
    @AfterThrowing("切点方法")


    
}

Spring两种AOP的实现

JDK动态代理(Spring默认):类要实现接口

CGLib:生成当前类的子类,所以类不能用final修饰

CGLib代理实现:有两种,一种是子类supper调用父类方法,还有一种就是把目标类当成属性,在方法前后增强之间调用目标类方法。

Spring一些常用的注解和作用

@Lazy 使bean懒加载

@Transactional 声明式事务

@Value 自定义注入用于普通字符,配置文件等

@RestController 作用在类上前后端分离直接返回JSON不走视图解析器

@AutoWired、自动装配

@Qualifier、自动装配

@Resource自动装配

@RequestMapping、

@GetMapping、

@PostMapping

@Configuration、

@Bean

@Component

@Service、

@Controller、

@Repository

Spring配置多个数据源是可以的 Bean容器到底是啥Bean是啥

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1007249.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号