spring学习1

1、bean实例化过程:bean实例化的基本流程,会将xml配置的bean信息封装成一个beandefinition对象,,所有的beandefinition会存储到一个beandefinition的map中,spring框架对该map进行遍历,并通过反射的方式创建bean实例对象,创建好的bean对象存放在singletonObjects的map集合中当使用getbean方法时,最终从该map集合中取出bean实例对象

2、spring的后置处理器:是spring开发的对外重要扩展点,支持动态注册beandefinition,动态修改beandefinition

BeanFactoryPostProcessor:在beandefinitionmap填充完毕,bean实例化之前进行调用,比如下面的手动注册bean,需要把自己实现的类配置到spring的xml中管理,可以通过自定义注解实现bean注册

java 复制代码
package com.example.demo10.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class myprocessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("beandifinition填充完毕后执行该方法");
        //注册beanDefinition
        BeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClassName("com.example.demo10.domain.Impl.PersonImpl");
        //强转成
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
        defaultListableBeanFactory.registerBeanDefinition("personDao",beanDefinition);
    }
}

@Test
    public void test8(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationcontext.xml");
        Object p = applicationContext.getBean(Person.class);
        System.out.println(p);
        applicationContext.close();
    }

BeanPostProcessor:在每个bean实例化之后,填充到单例池singletonObjects之前进行调用

java 复制代码
package com.example.demo10.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //可以在这里给创建的bean设置参数,打印日志等,即对bean的增强
        System.out.println(beanName+"postProcessBeforeInitialization");
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+"postProcessBeforeInitialization");
        return bean;
    }
}
java 复制代码
package com.example.demo10.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;

public class TimeProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        return bean;
    }

    /**
     * 通过动态代理,对现有的bean进行增强
     * 动态代理的实现依赖于 java.lang.reflect.Proxy 类和 InvocationHandler 接口。
     * 通过动态代理,可以在不修改原始类的情况下,为方法添加额外的逻辑,例如日志记录、权限校验等。
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Object beanProxy = Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                (proxy, method, args) ->{
                    //输出开始时间
                    System.out.println("方法:"+method.getName()+"-开始时间:"+new Date());
                    //执行目标方法
                    Object res = method.invoke(bean,args);
                    //输出结束时间
                    System.out.println("方法:"+method.getName()+"-结束时间:"+new Date());
                        return null;
                     }
        );

        //返回存入到单例池中
        return beanProxy;
    }
}

3、spring三级缓存解决循环引用问题,假如创建Abean,需要注入Bbean,创建Bbean需要注入Abean,spring会将没有注入参数的bean包装为一个factory并且存储到singletonfactory中,当创建Abean,会去三级缓存中找有没有Bbean,没有则去创建Bbean,Bbean创建时会去三级缓存中找有没有Abean,Abean此时在singletonfactory,会将Abean将singletonfactory移除,放入二级缓存earlysingletonObjects中,此时Bbean可以创建,当Bbean和Abean都被创建后,放入一级缓存singletonObjects中

4、spring常用注解:

java 复制代码
/**
 * @Component 注册类到spring容器,其bean name为userdao
 * @Scope 设置是单例还是多例
 * @PostConstruct:标记初始化方法
 * @PreDestroy:标记销毁方法
 * @Repository:标记dao层的类
 * @Service:标记service层的类
 * @Controller:标记web层的类
 * @Value:标记注入值给属性,通过配置文件读取
 * @Autowired:根据类型注入,先去匹配类型,类型有多个,再去匹配name
 * @Bean:将方法返回的bean注册到spring里,适用于调用返回第三方类
 * @Profile("test")  :标注属于哪个环境,比如当前这个只属于test环境,只有test环境被激活,才能使用该bean
 */
//@Component
@Repository
@Scope("singleton")
public class ToyDaoImpl implements ToyDao {

    @Value("S{toyname}")
    private String toyname;


    public String getToyname() {
        return toyname;
    }

    public ToyDaoImpl(){
        System.out.println("构造方法创建对象...");
    }

    @PostConstruct
    public void init(){
        System.out.println("初始化方法...");
    }

    @PreDestroy
    public void destory(){
        System.out.println("销毁方法...");
    }
}

5、配置类

java 复制代码
package com.example.demo10.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

/**
 * spring的配置类,用来代替spring的配置文件
 */

@Configuration  //标注当前类是一个配置类,把当前的类放入spring容器管理
@ComponentScan(basePackages = {"com.example.demo10"})  //标注扫描基本包,把该包里的类交给spring管理
@PropertySource("classpath:kv.properties")  //加载配置文件
@Import(DataSource.class)
public class SpringConfig {
}

6、@Component会将扫描到的所有类,通过dosacn注册到beandefinitionmap中,执行bean的生命周期,最终生成实例bean

相关推荐
海绵宝宝转agent6 分钟前
Pico 学习笔记 Harness 设计、历史压缩、三类目录与缓存复用
笔记·学习·缓存
DongQiShanRen22 分钟前
裁决台账双向互校(上):名册与实物的第一道对账
java·linux·运维·数据库·人工智能·自然语言处理·数据挖掘
cpolar技术支持1 小时前
Spring Boot 接口本地正常,异地前端却报跨域?用 cpolar 跑通 CORS 预检与白名单
java·springboot·cpolar·前后端分离·cors
wuminyu1 小时前
Virtual Thread重投递至ForkJoinPool任务队列过程解析
java·linux·c语言·jvm·c++
我命由我123451 小时前
Photoshop - Photoshop 使用仿制图章工具移除对象
学习·职场和发展·产品运营·求职招聘·职场发展·产品经理·学习方法
传奇开心果编程1 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
哼べ要伱管1 小时前
26秋季上册-广东省电子基础性作业(小学)
经验分享·学习
JWASX1 小时前
Java 转 go 学习 - 并发编程(2)
学习·golang
小蒜学长1 小时前
在线保险服务与管理平台的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·服务平台·在线保险
掉进电商坑三年没爬出来的东叔1 小时前
青龙面板进阶:一个面板聚合多平台签到,所有积分自动领
java·开发语言