Spring 框架容器管理注解和生命周期

Spring 注解

在 Spring 框架中,大量的注解是由 Spring 容器(而不是虚拟机)进行处理和解析的。Spring 框架使用了反射和自定义的处理机制来解析注解,并根据注解的定义执行相应的逻辑。

Spring 框架中的注解主要用于配置和控制应用程序的行为,例如声明 Bean、依赖注入、AOP 等。以下是一些常用的 Spring 注解及其作用:

  • @Component:用于标记一个类为 Spring 组件,会被 Spring 自动扫描并创建实例。
  • @Autowired:用于自动注入依赖对象。
  • @RequestMapping:用于映射 HTTP 请求到处理方法。
  • @Transactional:用于声明事务管理。
  • @Aspect@Before@After 等:用于声明切面和切点,实现 AOP 功能。

当使用了这些注解时,Spring 容器会在应用程序启动时扫描所配置的包,并解析这些注解。它会通过反射机制获取注解信息,并根据注解的定义执行相应的逻辑,例如创建 Bean 实例、自动注入依赖、生成代理对象等。

Spring 框架还提供了一些工具类和接口,用于处理和解析注解,例如 AnnotationUtilsAnnotatedElementUtilsAnnotationConfigApplicationContext 等。这些工具和接口可以让开发人员更方便地处理和访问注解信息。

需要注意的是,虽然 Spring 框架在运行时使用了反射来处理注解,但这并不是虚拟机自动处理的。相反,Spring 框架提供了一套机制,用于解释和执行这些注解,并在应用程序运行时根据注解的定义来完成相应的功能。

Spring 容器

在 Spring 框架中,Spring 容器是一个负责创建、管理和组织应用程序中各个组件(Bean)的容器。它提供了一种便捷的方式来管理对象的生命周期、依赖注入和解析、AOP 等功能。

Spring 容器主要有两种类型:BeanFactory 和 ApplicationContext。

  1. BeanFactory:这是 Spring 容器的基本接口,定义了最简单的容器功能。它提供了对 Bean 的创建、获取、销毁等基本操作。示例代码如下:
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class MainApp {
    public static void main(String[] args) {
        BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        MyBean myBean = (MyBean) factory.getBean("myBean");
        myBean.doSomething();
    }
}
  1. ApplicationContext:这是 BeanFactory 接口的扩展,提供了更多的高级功能。它是 Spring 容器的完整实现,支持国际化、资源加载、事件发布等特性。示例代码如下:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        MyBean myBean = (MyBean) context.getBean("myBean");
        myBean.doSomething();
    }
}

在这两个示例中,spring-config.xml 是一个 XML 配置文件,用于定义 Bean 的配置和依赖关系。在实际应用中,可以使用不同的配置方式,如注解或 Java Config,来定义 Bean。

Spring 容器会读取配置文件并根据配置信息创建相应的 Bean 对象。通过调用容器的 getBean() 方法,可以获取到已经创建的 Bean 实例,并使用其提供的功能。

总结来说,Spring 容器是一个负责管理和组织应用程序中各个组件的容器,它可以根据配置信息创建、初始化和管理对象。通过使用 Spring 容器,可以实现依赖注入、AOP、事务管理等功能,使开发人员可以更加专注于业务逻辑的实现。

Spring 容器中 BeanFactory

public class BeanFactory implements ObjectFactory {

    private static final StringManager sm = StringManager.getManager(BeanFactory.class);

    private final Log log = LogFactory.getLog(BeanFactory.class); // Not static

    /**
     * Create a new Bean instance.
     *
     * @param obj The reference object describing the Bean
     */
    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?,?> environment)
            throws NamingException {

        if (obj instanceof ResourceRef) {

            try {
                Reference ref = (Reference) obj;
                String beanClassName = ref.getClassName();
                Class<?> beanClass = null;
                ClassLoader tcl = Thread.currentThread().getContextClassLoader();
                try {
                    if (tcl != null) {
                        beanClass = tcl.loadClass(beanClassName);
                    } else {
                        beanClass = Class.forName(beanClassName);
                    }
                } catch(ClassNotFoundException cnfe) {
                    NamingException ne = new NamingException(sm.getString("beanFactory.classNotFound", beanClassName));
                    ne.initCause(cnfe);
                    throw ne;
                }

                BeanInfo bi = Introspector.getBeanInfo(beanClass);
                PropertyDescriptor[] pda = bi.getPropertyDescriptors();

                Object bean = beanClass.getConstructor().newInstance();

                // Look for the removed forceString option
                RefAddr ra = ref.get("forceString");
                if (ra != null) {
                    log.warn(sm.getString("beanFactory.noForceString"));
                }

                Enumeration<RefAddr> e = ref.getAll();
                String value;

                while (e.hasMoreElements()) {

                    ra = e.nextElement();
                    String propName = ra.getType();

                    if (propName.equals(Constants.FACTORY) ||
                        propName.equals("scope") || propName.equals("auth") ||
                        propName.equals("forceString") ||
                        propName.equals("singleton")) {
                        continue;
                    }

                    value = (String)ra.getContent();

                    Object[] valueArray = new Object[1];

                    int i = 0;
                    for (i = 0; i < pda.length; i++) {

                        if (pda[i].getName().equals(propName)) {

                            Class<?> propType = pda[i].getPropertyType();
                            Method setProp = pda[i].getWriteMethod();

                            if (propType.equals(String.class)) {
                                valueArray[0] = value;
                            } else if (propType.equals(Character.class) || propType.equals(char.class)) {
                                valueArray[0] = Character.valueOf(value.charAt(0));
                            } else if (propType.equals(Byte.class) || propType.equals(byte.class)) {
                                valueArray[0] = Byte.valueOf(value);
                            } else if (propType.equals(Short.class) || propType.equals(short.class)) {
                                valueArray[0] = Short.valueOf(value);
                            } else if (propType.equals(Integer.class) || propType.equals(int.class)) {
                                valueArray[0] = Integer.valueOf(value);
                            } else if (propType.equals(Long.class) || propType.equals(long.class)) {
                                valueArray[0] = Long.valueOf(value);
                            } else if (propType.equals(Float.class) || propType.equals(float.class)) {
                                valueArray[0] = Float.valueOf(value);
                            } else if (propType.equals(Double.class) || propType.equals(double.class)) {
                                valueArray[0] = Double.valueOf(value);
                            } else if (propType.equals(Boolean.class) || propType.equals(boolean.class)) {
                                valueArray[0] = Boolean.valueOf(value);
                            } else if (setProp != null) {
                                // This is a Tomcat specific extension and is not part of the
                                // Java Bean specification.
                                String setterName = setProp.getName();
                                try {
                                    setProp = bean.getClass().getMethod(setterName, String.class);
                                    valueArray[0] = value;
                                } catch (NoSuchMethodException nsme) {
                                    throw new NamingException(sm.getString(
                                            "beanFactory.noStringConversion", propName, propType.getName()));
                                }
                            } else {
                                throw new NamingException(sm.getString(
                                        "beanFactory.noStringConversion", propName, propType.getName()));
                            }

                            if (setProp != null) {
                                setProp.invoke(bean, valueArray);
                            } else {
                                throw new NamingException(sm.getString("beanFactory.readOnlyProperty", propName));
                            }

                            break;
                        }
                    }

                    if (i == pda.length) {
                        throw new NamingException(sm.getString("beanFactory.noSetMethod", propName));
                    }
                }

                return bean;

            } catch (java.beans.IntrospectionException ie) {
                NamingException ne = new NamingException(ie.getMessage());
                ne.setRootCause(ie);
                throw ne;
            } catch (java.lang.ReflectiveOperationException e) {
                Throwable cause = e.getCause();
                if (cause instanceof ThreadDeath) {
                    throw (ThreadDeath) cause;
                }
                if (cause instanceof VirtualMachineError) {
                    throw (VirtualMachineError) cause;
                }
                NamingException ne = new NamingException(e.getMessage());
                ne.setRootCause(e);
                throw ne;
            }

        } else {
            return null;
        }
    }
}

Spring 中注解的处理机制

在 Spring 框架中,注解的处理机制是通过反射和基于注解的配置来实现的。Spring 可以通过扫描类路径或者指定的包路径,自动识别和处理注解,从而实现一些特定的功能。

以下是 Spring 中常见注解的处理机制:

  1. 组件扫描:Spring 提供了 @ComponentScan 注解用于指定要扫描的包路径,从而自动发现带有特定注解的类。在启动应用时,Spring 将扫描指定包路径下的所有类,并将带有 @Component 及其衍生注解(如 @Service@Repository@Controller)的类注册为 Bean。

  2. Bean 定义:通过注解可以方便地定义 Bean,例如 @Component@Service@Repository@Controller 等。这些注解告诉 Spring 在扫描到对应的类时将其注册为 Bean。

  3. 依赖注入:Spring 提供了 @Autowired 注解用于自动装配 Bean,它可以标记在字段、构造函数或方法上,Spring 将根据类型进行匹配并将依赖的 Bean 自动注入到对应的位置。

  4. 切面编程:通过注解可以方便地定义切面和通知,例如 @Aspect@Before@After@Around 等。这些注解可以让开发者在不修改原有业务代码的情况下,方便地实现横切关注点的功能。

  5. 事务管理:使用 @Transactional 注解可以简化事务的管理,通过在方法或类上添加该注解,在满足条件的情况下 Spring 将自动为方法添加事务支持。

总的来说,Spring 通过扫描注解并结合反射机制,实现了自动发现、自动装配和自动化配置功能,使得开发者可以更加方便地进行组件化开发和集成各种功能。同时,通过注解的方式可以减少 XML 配置文件的使用,使得配置更为简洁和易读。.

根据不同的注解生成不同的业务逻辑

通过在控制器类和请求处理方法上使用不同的注解,我们可以将不同的请求映射到不同的方法上,并实现相应的业务逻辑。在 Spring 框架中,这些注解会被扫描并识别,从而自动为我们生成相应的代码逻辑。

你可能感兴趣的:(Spring,Java,spring,java,后端)