spring 核心知识

2020-04-13  本文已影响0人  jiahzhon

什么是spring

主要模块

Spring AOP : AOP服务
Spring Core : 核心库类,提供IOC服务
Spring Context : 提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等)
Spring DAO : 对JDBC的抽象 ,简化了数据库访问异常的处理
Spring ORM : 对现有的ORM框架的支持
Spring Web : 提供了基本的面向Web的综合特性
Spring MVC : 提供面向Web应用的Model-View-Controller实现

spring IOC

BeanFactory

ApplicationContext

spingboot源码指的classpath

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { 
    "classpath:/META-INF/resources/", 
    "classpath:/resources/", 
    "classpath:/static/", 
    "classpath:/public/" }; 
public class UserRegisterEvent extends ApplicationEvent{
    public UserRegisterEvent(String name) { //name即source
        super(name);
    }
}
@Service
public class UserService implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher applicationEventPublisher;
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
    public void register(String name) {
        System.out.println("用户:" + name + " 已注册!");
        applicationEventPublisher.publishEvent(new UserRegisterEvent(name));
    }
}
@Service
public class EmailService implements ApplicationListener<UserRegisterEvent> {
    @Override
    public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {
        System.out.println("邮件服务接到通知,给 " + userRegisterEvent.getSource() + " 发送邮件...");
    }
}

BeanFactory和ApplicationContext

两者装载bean的区别:
BeanFactory:
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;

ApplicationContext:
ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;

各自优点:

  1. 所有的Bean在启动的时候都加载,系统运行的速度快;

  2. 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题

  3. 建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)

Spring Bean 作用域(用于判断bean的个数)

Spring Bean 生命周期

  1. Spring对Bean进行实例化(相当于程序中的new Xx())

  2. Spring将值和Bean的引用注入进Bean对应的属性中,利用IOC

  3. 如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法(实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)

  4. 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory bf)方法并把BeanFactory容器实例作为参数传入。(实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)

  5. 如果Bean实现了ApplicationContextAware接口,Spring容器将调用setApplicationContext(ApplicationContext ctx)方法,把应用上下文作为参数传入.(作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory )

  6. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法(作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,(增加某个功能,这个很重要,AOP就是在这里实现的)

  7. 如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。

  8. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessAfterInitialization(后初始化)方法(作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 ) 这个时候已经再被使用了

  9. 经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁

  10. 如果Bean实现了DispostbleBean接口,Spring将调用它的destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。

// 忽略了无关代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (instanceWrapper == null) {
       // 实例化阶段!
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
       // 属性赋值阶段!
      populateBean(beanName, mbd, instanceWrapper);
       // 初始化阶段!
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }

   
   }

当容器关闭时调用bean的销毁方法

Spring Bean 依赖注入

● 理解基于构造函数的依赖注入

/*带参数,方便利用构造器进行注入*/ 
 public CatDaoImpl(String message){ 
 this. message = message; 
 } 
<bean id="CatDaoImpl" class="com.CatDaoImpl"> 
<constructor-arg value=" message "></constructor-arg> 
</bean>

● 理解基于设置函数的依赖注入

public class Id { 
 private int id; 
 public int getId() { return id; } 
 public void setId(int id) { this.id = id; } 
} 
<bean id="id" class="com.id "> <property name="id" value="123"></property> </bean>

● 基于自动装配的依赖注入(配置文件里不用写依赖关系了,有相应的方法就行)
byType(类型模式),byName(名称模式)、constructor(构造函数模式)

● 基于注解的依赖注入(方法都省略了)
@Autowired @Resource

Spring AOP

AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
1、切面(aspect):一般就是一个类。切入点 + 通知,通俗点就是:在什么时机,什么地方,做什么增强!
2、横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。 (相对于核心关注点来说的)
3、连接点(joinpoint):连接点是在应用执行过程中能够插入切面(Aspect)的一个点。这些点可以是调用方法时、甚至修改一个字段时。虚的概念
4、切入点(pointcut):在哪些类,哪些方法上切入(where)
5、通知(advice):在方法执行的什么实际(when:方法前/方法后/方法前后)做什么(what:增强的功能),通知分为前置、后置、异常、最终、环绕通知五类。
6、目标对象:代理的目标对象。
7、织入(weave):把切面加入到对象,并创建出代理对象的过程。(由 Spring 来完成)
8、引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。

@Aspect
public class TransactionDemo {
   @Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
   public void point(){
   }

   @Before(value="point()")
   public void before(){
     System.out.println("transaction begin");
   }

   @AfterReturning(value = "point()")
   public void after(){
     System.out.println("transaction commit");
   }

   @Around("point()")
   public void around(ProceedingJoinPoint joinPoint) throws Throwable{
     System.out.println("transaction begin");
     joinPoint.proceed();
     System.out.println("transaction commit");
 } }
上一篇下一篇

猜你喜欢

热点阅读