spring

我怕爱的太早我们不能终老 提交于 2020-02-21 23:53:07

什么是spring?

  简单来说 ,spring就是一个轻量级的java开发框架,用来开发企业级应用,让开发者专注于业务,而不是底层的框架。

为什么要用spring?

  spring的核心概念有两个IOC和AOP。IOC(Inversion of Control)也就是常说的控制反转,它和我们平时编程有啥不一样呢?我们平时编程都是使用new来实例化类或者其他的一些方法。这样有一个坏处,那就是你的应用程序和你使用的类紧紧耦合在了一起,复用起来很不方便。因为要使用你的程序必须要有你实例化的类,而且一旦你使用的类发生了改变,你的整个程序都需要改变。IOC就是为了解决这个问题,使用@Autowired注解像这样:

@Autowired
SomeObject object;

你就可以使用这个类的实例了,这里的SomeObject一般是一个接口,这样你的应用程序就和实际的类解耦合了,当类发生改变时应用程序不需要做任何改变。那么重点来了spring怎么实现控制反转这一编程思想的?

spring容器的实现

  spring中IOC的实现是通过BeanFactory这一接口,这个接口代表了一个IOC容器,IOC容器包含了你配置的需要使用的类的实例,你可以使用@Autowired注解或者直接通过getBean方法获取你配置的类的实例。接口的详细代码如下:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";



    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;


    Object getBean(String name, Object... args) throws BeansException;


    <T> T getBean(Class<T> requiredType) throws BeansException;


    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);


    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);


    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;


    String[] getAliases(String name);

}

  在spring中还有一个概念叫做应用上下文,抽象出来的接口是ApplicationContext,应用上下文其实也是一个容器,但是它比容器具有更多的功能,spring真正使用的是应用上下文。BeanFactory相当于一个基础设施。

AOP简单介绍

AOP 面向切面编程,什么意思?你就想一个问题,有一个功能在应用程序的每个地方都需要用到,帮这个功能抽象出来而不是散落在程序的各个角落。这和一个切面是不是很像,这个其他方法调用时都需要从这个切面通过。具体实现呢我不知道

spring的使用

 spring在Java Web程序中的启动

  web.xml中配置启动

 

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
     <!--这个是父上下文的配置文件位置-->
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>

 

  编程式启动

 

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
       //AppConfig是上下文的配置类
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
      //spring mvc 映射设置
        registration.addMapping("/app/*");
    }
}

 为什么tomcat容器会加载WebApplicationInitializer类来注册上下文和DispatcherServlet?原因是由于spring实现了ServletContainerInitializer(这个是servlet技术中的接口)这个接口,并把WebApplicationInitializer声明为了需要处理的类型源码如下://处理类型的声明

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {


    @Override
    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
            throws ServletException {

        List<WebApplicationInitializer> initializers = new LinkedList<>();

        if (webAppInitializerClasses != null) {
            for (Class<?> waiClass : webAppInitializerClasses) {
                // Be defensive: Some servlet containers provide us with invalid classes,
                // no matter what @HandlesTypes says...
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
                        WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((WebApplicationInitializer)
                                ReflectionUtils.accessibleConstructor(waiClass).newInstance());
                    }
                    catch (Throwable ex) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
            return;
        }

        servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
        AnnotationAwareOrderComparator.sort(initializers);
        for (WebApplicationInitializer initializer : initializers) {        //调用对应的方法初始化上下文
            initializer.onStartup(servletContext);
        }
    }

}

在springMVC中一般有两个应用上下文,一个是ContextLoaderListner加载的上下文,还有一个时DispatcherServlet加载的上下文。者两个上下文是父子关系。父上下文中的bean可以继承到子上下文中。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!