手写简易版Springv1源码

v1版本
目录结构
在这里插入图片描述
类图
在这里插入图片描述

注解

@Target({
    
    ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_Autowired {
    
    
	String value() default "";
}

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_Controller {
    
    
	String value() default "";
}

@Target({
    
    ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_RequestMapping {
    
    
	String value() default "";
}

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_RequestParam {
    
    
	String value() default "";
	boolean required() default true;

}


@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PABLO_Service {
    
    
	String value() default "";
}
package com.gator.spring.framework.context;

import com.gator.spring.framework.annotation.PABLO_Autowired;
import com.gator.spring.framework.annotation.PABLO_Controller;
import com.gator.spring.framework.annotation.PABLO_Service;
import com.gator.spring.framework.beans.PABLO_BeanFactory;
import com.gator.spring.framework.beans.PABLO_BeanWrapper;
import com.gator.spring.framework.beans.config.PABLO_BeanPostProcessor;
import com.gator.spring.framework.beans.factory.config.PABLO_BeanDefinition;
import com.gator.spring.framework.beans.support.PABLO_BeanDefinitionReader;
import com.gator.spring.framework.beans.support.PABLO_DefaultListableBeanFactory;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Authror PABLO
 * @Date 2022/5/7 11:25
 * @Desc 继承默认的IOC容器  
 */
public class PABLO_ApplicationContext
        extends PABLO_DefaultListableBeanFactory{
    
    


    private String[] configLocations;
    //封装definition规范方法
    private PABLO_BeanDefinitionReader reader;

    //单例的IOC容器缓存
    private Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
    //通用的IOC容器  缓存wrapper
    private Map<String, PABLO_BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<String, PABLO_BeanWrapper>();


    public PABLO_ApplicationContext(String... configLocations) {
    
    
        this.configLocations = configLocations;
        try {
    
    
            refresh();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    @Override
    public void refresh() throws Exception {
    
    
        //定位配置文件
        reader = new PABLO_BeanDefinitionReader(this.configLocations);
        //扫描加载代内存的类,封装为definition规范
        List<PABLO_BeanDefinition> beanDefinitions = reader.loadBeanDefinitions();
        //注册 将配置信息注册到beanDefinitionMap中
        doRegisterBeanDefinition(beanDefinitions);
        //将非延迟加载的类,提前初始化
        doAutowired();



        System.out.println(singletonObjects);

    }

    private void doAutowired() {
    
    
        for (Map.Entry<String, PABLO_BeanDefinition> beanDefinitionEntry : super.beanDefinitionMap.entrySet()) {
    
    
            //beanFactory中的name,默认首字母小写
            String beanName = beanDefinitionEntry.getKey();
            //非懒加载直接getBean
            if (!beanDefinitionEntry.getValue().isLazyInit()) {
    
    
                try {
    
    
                    getBean(beanName);
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

    private void doRegisterBeanDefinition(List<PABLO_BeanDefinition> beanDefinitions) throws Exception {
    
    
        for (PABLO_BeanDefinition beanDefinition : beanDefinitions) {
    
    
            if (super.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())) {
    
    
                throw new Exception("The “" + beanDefinition.getFactoryBeanName() + "” is exists!!");
            }
            super.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(), beanDefinition);
        }
    }

    /**
     * @Description: 通过class获取对象
     * @Author: PABLO
     * @Date: 2022/5/7 20:38
     * @Params: [clazz]
     * @Return: java.lang.Object
     **/
    public Object getBean(Class clazz) throws Exception {
    
    
        return getBean(clazz.getName());
    }

    /**
     * @Description: 根据beanName实例化并初始化对象
     * @Author: PABLO
     * @Date: 2022/5/7 17:27
     * @Params: [beanName 支持类的完全限定名 和 首字母小写类名]
     * @Return: java.lang.Object
     **/
    @Override
    public Object getBean(String beanName) throws Exception {
    
    

        //先考虑只有单例
        //存在直接拿
        if (this.singletonObjects.containsKey(beanName)) {
    
    
            return this.singletonObjects.get(beanName);
        }
        //1.实例化
        //获取对象的描述信息
        PABLO_BeanDefinition pablo_beanDefinition = beanDefinitionMap.get(beanName);

        //根据名称和对应的描述信息实例化bean
        Object instance = instantiateBean(beanName, pablo_beanDefinition);

        //将对象封装到beanWrapper中
        PABLO_BeanWrapper beanWrapper = new PABLO_BeanWrapper(instance);

        //存储IOC容器
        factoryBeanInstanceCache.put(beanName, beanWrapper);
        //--------------------------------------------------------------------------
        //增强器
        PABLO_BeanPostProcessor postProcessor = new PABLO_BeanPostProcessor();
        //前置增强器
        postProcessor.postProcessBeforeInitialization(instance, beanName);
        //初始化
        populateBean(beanName, new PABLO_BeanDefinition(), beanWrapper);
        //后置增强器
        postProcessor.postProcessAfterInitialization(instance, beanName);

        return this.factoryBeanInstanceCache.get(beanName).getWrappedInstance();
    }

    private void populateBean(String beanName, PABLO_BeanDefinition pablo_beanDefinition, PABLO_BeanWrapper beanWrapper) {
    
    
        Object instance = beanWrapper.getWrappedInstance();
        //获得实例对象的类 class com.gator.spring.executor.service.impl.xxxClass
        Class<?> clazz = beanWrapper.getWrappedClass();

        //判断只有加了注解的类,才执行依赖注入
        if (!(clazz.isAnnotationPresent(PABLO_Controller.class) || clazz.isAnnotationPresent(PABLO_Service.class)))
            return;
        //获得所有的fields
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
    
    
            //没有注入注解跳过
            if (!field.isAnnotationPresent(PABLO_Autowired.class)) continue;
            PABLO_Autowired autowired = field.getAnnotation(PABLO_Autowired.class);
            //获取注解上的value值
            String autowiredBeanName = autowired.value().trim();
            //“”默认类型名字
            if ("".equals(autowiredBeanName)) autowiredBeanName = field.getType().getName();
            //强制访问
            field.setAccessible(true);
            try {
    
    
                if (this.factoryBeanInstanceCache.get(autowiredBeanName) == null) {
    
    
                    continue;
                }
                //属性注入
                field.set(instance, this.factoryBeanInstanceCache.get(autowiredBeanName).getWrappedInstance());
            } catch (IllegalAccessException e) {
    
    
                e.printStackTrace();
            }

        }
    }


    //beanName可能是小写名,也可能是全路径
    private Object instantiateBean(String beanName, PABLO_BeanDefinition pablo_beanDefinition) {
    
    
        Object instance = null;
        try {
    
    
                //获取该类完全限定名
                String className = pablo_beanDefinition.getBeanClassName();
                //反射创建
                Class<?> clazz = Class.forName(className);
                instance = clazz.newInstance();
                //this.singletonObjects.put(className, instance);
                //实现通过完全限定名和类名小写都能获取到对象
                this.singletonObjects.put(beanName, instance);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return instance;
    }


}
package com.gator.spring.framework.beans.support;

import com.gator.spring.framework.beans.PABLO_BeanFactory;
import com.gator.spring.framework.beans.factory.config.PABLO_BeanDefinition;
import com.gator.spring.framework.context.support.PABLO_AbstractApplicationContext;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author PABLO
 * @Date 2022/5/7 11:36
 * @Desc IOC容器的默认实现  兜底
 */
public class PABLO_DefaultListableBeanFactory
        extends PABLO_AbstractApplicationContext
        implements PABLO_BeanFactory{
    
    


    //存储对象描述信息map集合
    //key为对象在BeanFactory中的名称,默认小写字母开头
    public final Map<String, PABLO_BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, PABLO_BeanDefinition>(256);

    @Override
    public Object getBean(String beanName) throws Exception {
    
    
        return null;
    }
}
package com.gator.spring.framework.context.support;

/**
 * @Author PABLO
 * @Date 2022/5/7 11:30
 * @Desc IOC容器的顶层设计
 */
public abstract class PABLO_AbstractApplicationContext {
    
    
    
    /**
     * @Description: 模板方法,供子类重写生效 可一键重启
     * @Author: PABLO
     * @Date: 2022/5/7 11:32
     * @Params: 
     * @Return: 
     **/
    protected void refresh() throws Exception {
    
    }
}
package com.gator.spring.framework.beans;

/**
 * @Authror PABLO
 * @Date 2022/5/7 11:21
 * @Desc 单例工厂的顶层设计
 */
public interface PABLO_BeanFactory {
    
    

    /**
     * @Description: 根据beanName获取对象
     * @Author: PABLO
     * @Date: 2022/5/7 11:23
     * @Params: [beanName]
     * @Return: java.lang.Object
     **/
    Object getBean(String beanName) throws Exception;

}
package com.gator.spring.framework.beans.config;

/**
 * @Author PABLO
 * @Date 2022/5/7 13:13
 * @Desc bean初始化增强器
 */
public class PABLO_BeanPostProcessor {
    
    

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
    
    
        System.out.println( "-----"+beanName+"初始化对象之前");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
    
    
        System.out.println( "-----"+beanName+"初始化对象之后");
        return bean;
    }
}
package com.gator.spring.framework.beans.factory.config;

import lombok.Data;

/**
 * @Author PABLO
 * @Date 2022/5/7 11:45
 * @Desc bean描述,存储配置信息
 */
@Data
public class PABLO_BeanDefinition {
    
    

    private String beanClassName; //类的完全限定名
    private String factoryBeanName; //对象正在工厂内的名称,默认首字母小写
    private boolean lazyInit = false;
}
package com.gator.spring.framework.beans.support;

import com.gator.spring.framework.beans.factory.config.PABLO_BeanDefinition;
import com.sun.deploy.security.BadCertificateDialog;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @Author PABLO
 * @Date 2022/5/7 12:19
 * @Desc definition读取器
 */
public class PABLO_BeanDefinitionReader {
    
    

    //保存所有需要注册的class
    private List<String> registryBeanClasses = new ArrayList<String>();

    private Properties config = new Properties();

    //固定配置文件中的key,相对于xml的规范
    private final String SCAN_PACKAGE = "scanPackage";

    /**
     * @Description: 将入参配置文件加载到内存
     * @Author: PABLO
     * @Date: 2022/5/7 12:21
     * @Params: [locations]
     * @Return:
     **/
    public PABLO_BeanDefinitionReader(String... locations) {
    
    

        //通过URL定位找到其所对应的文件,然后转换为文件流
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:", ""));
        try {
    
    
            //加载配置
            config.load(is);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (null != is) {
    
    
                try {
    
    
                    is.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        //多路径扫描
        String property = config.getProperty(SCAN_PACKAGE);
        for (String scanPackage : property.split(",")) {
    
    
            doScanner(scanPackage);
        }

    }

    private void doScanner(String scanPackage) {
    
    
        //转换为文件路径,实际上就是把.替换为/就OK了
        //处理每个包,将包路径转为文件路径  .-->/
        URL url = this.getClass()./*getClassLoader().*/getResource("/" + scanPackage.replaceAll("\\.", "/"));
        System.out.println("url" + url);
        File dir = new File(url.getFile());
        for (File file : dir.listFiles()) {
    
    
            //如果是文件夹,继续递归
            if (file.isDirectory()) {
    
    
                doScanner(scanPackage + "." + file.getName());
            } else {
    
    
                //E:\IDEALocation\giant-gator\target\classes\com\bj\summary\spring_mvc\controller\TestController.class
                registryBeanClasses.add(scanPackage + "." + file.getName().replace(".class", "").trim());
            }
        }
    }

    public Properties getConfig() {
    
    
        return this.config;
    }


    /**
     * @Description: 配置信息封装为definition规范
     *              注意:我这里定义的规则是:(可自定义)
     *                  如果是实现类,可使用实现类完全限定名/实现类首字母小写/接口完全限定名/
     *                  如果是普通类,可使用类的完全限定名/类名小写getBean获取对象
     * @Author: PABLO
     * @Date: 2022/5/7 12:29
     * @Params: []
     * @Return: java.util.List<GPBeanDefinition>
     **/
    public List<PABLO_BeanDefinition> loadBeanDefinitions() {
    
    

        List<PABLO_BeanDefinition> result = new ArrayList<PABLO_BeanDefinition>();
        try {
    
    
            for (String className : registryBeanClasses) {
    
    
                Class<?> beanClass = Class.forName(className);
                //如遇接口使用其实现类初始化
                if (beanClass.isInterface()) continue;
                //beanName有三种情况:
                //1、默认是类名首字母小写
                //2、自定义名字
                //3、接口注入
                //判断首字母大小写,如小写直接添加,如大写需转换
                //beanClass.getSimpleName()是类名
                //beanClass.getName()是类的完全限定名
                //保存小写名称的映射关系
                char c = beanClass.getSimpleName().toCharArray()[0];
                result.add(doCreateBeanDefinition(Character.isLowerCase(c)
                                ? beanClass.getSimpleName()
                                : toLowerFirstCase(beanClass.getSimpleName()),
                        beanClass.getName()));
                //保存完全限定名的映射关系
                result.add(doCreateBeanDefinition(beanClass.getName(), beanClass.getName()));
                //获取该实现类的接口列表
                Class<?>[] interfaces = beanClass.getInterfaces();
                for (Class<?> i : interfaces) {
    
    
                    //如果是多个实现类,只能覆盖
                    //为什么?因为Spring没那么智能,就是这么傻
                    //这个时候,可以自定义名字
                    //保存接口的完全限定名的映射关系
                    result.add(doCreateBeanDefinition(i.getName(), beanClass.getName()));
                }

            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return result;
    }

    /**
     * @Description: 将配置信息解析为definition规范
     * @Author: PABLO
     * @Date: 2022/5/7 12:31
     * @Params: [factoryBeanName, beanClassName 是完全限定名]
     * @Return: GPBeanDefinition
     **/
    private PABLO_BeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName) {
    
    

        PABLO_BeanDefinition beanDefinition = new PABLO_BeanDefinition();
        beanDefinition.setBeanClassName(beanClassName);
        beanDefinition.setFactoryBeanName(factoryBeanName);
        System.out.println(beanDefinition);
        return beanDefinition;
    }

    /**
     * @Description:大写转小写
     * @Author: PABLO
     * @Date: 2022/5/7 12:34
     * @Params: [simpleName]
     * @Return: java.lang.String
     **/
    private String toLowerFirstCase(String simpleName) {
    
    
        char[] chars = simpleName.toCharArray();
        //大小写字母的ASCII码相差32,
        //而且大写字母的ASCII码要小于小写字母的ASCII码
        //在Java中,对char做算学运算,实际上就是对ASCII码做算学运算
        chars[0] += 32;
        return String.valueOf(chars);
    }

}
package com.gator.spring.framework.beans.support;

import com.gator.spring.framework.beans.PABLO_BeanFactory;
import com.gator.spring.framework.beans.factory.config.PABLO_BeanDefinition;
import com.gator.spring.framework.context.support.PABLO_AbstractApplicationContext;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author PABLO
 * @Date 2022/5/7 11:36
 * @Desc IOC容器的默认实现  兜底
 */
public class PABLO_DefaultListableBeanFactory
        extends PABLO_AbstractApplicationContext
        implements PABLO_BeanFactory{
    
    


    //存储对象描述信息map集合
    //key为对象在BeanFactory中的名称,默认小写字母开头
    public final Map<String, PABLO_BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, PABLO_BeanDefinition>(256);

    @Override
    public Object getBean(String beanName) throws Exception {
    
    
        return null;
    }
}
package com.gator.spring.framework.beans;

/**
 * @Author PABLO
 * @Date 2022/5/7 12:47
 * @Desc 对象包装类  创建对象成功后返回的装饰器
 */
public class PABLO_BeanWrapper {
    
    

    //被包装的bean实例
    private Object wrappedInstance;

    private Class<?> wrappedClass;

    public PABLO_BeanWrapper(Object wrappedInstance){
    
    
        this.wrappedInstance = wrappedInstance;
    }

    public Object getWrappedInstance(){
    
    
        return this.wrappedInstance;
    }

    // 返回代理以后的Class
    // 可能会是这个 $Proxy0
    public Class<?> getWrappedClass(){
    
    
        return this.wrappedInstance.getClass();
    }
}
/**
 * @Authror PABLO
 * @Date 2022/5/7 11:21
 * @Desc
 */
public interface PABLO_FactoryBean {
    
    
}
package com.gator.spring.framework.context;

import org.springframework.beans.BeansException;


/**
 * @Authror PABLO
 * @Date 2022/5/7 11:58
 * @Desc 解耦获得IOC容器的顶层设计
 *       通过监听器(Observer)扫描所有类,只要实现此接口,将调用setApplicationContext(),将IOC容器注入到目标类中
 */
public interface PABLO_ApplicationContextAware {
    
    

    void setApplicationContext(PABLO_ApplicationContext applicationContext) throws BeansException;
}

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.7</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.giant-gator.spring</groupId>
	<artifactId>gator-spring</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>gator.spring</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
        </dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.25</version>
		</dependency>

		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.2.3</version>
		</dependency>
    </dependencies>

	<build>
		<finalName>${
    
    artifactId}</finalName>
		<resources>
			<resource>
				<directory>${
    
    basedir}/src/main/resources</directory>
				<includes>
					<include>**/*</include>
				</includes>
			</resource>
			<resource>
				<directory>${basedir}/src/main/java</directory>
				<excludes>
					<exclude>**/*.java</exclude>
					<exclude>**/*.class</exclude>
				</excludes>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
					<compilerArguments>
						<verbose />
						<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
					</compilerArguments>
				</configuration>
			</plugin>

			<plugin>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.5</version>
				<executions>
					<execution>
						<id>copy-resources</id>
						<!-- here the phase you need -->
						<phase>validate</phase>
						<goals>
							<goal>copy-resources</goal>
						</goals>
						<configuration>
							<encoding>UTF-8</encoding>
							<outputDirectory>${basedir}/target/classes</outputDirectory>
							<resources>
								<resource>
									<directory>src/main/resources</directory>
									<includes>
										<include>**/*.*</include>
									</includes>
									<filtering>true</filtering>
								</resource>
							</resources>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<version>6.1.26</version>
				<configuration>
					<webDefaultXml>src/main/resources/webdefault.xml</webDefaultXml>
					<contextPath>/</contextPath>
					<connectors>
						<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
							<port>80</port>
						</connector>
					</connectors>
					<scanIntervalSeconds>0</scanIntervalSeconds>
					<scanTargetPatterns>
						<scanTargetPattern>
							<directory>src/main/webapp</directory>
							<includes>
								<include>**/*.xml</include>
								<include>**/*.properties</include>
							</includes>
						</scanTargetPattern>
					</scanTargetPatterns>
					<systemProperties>
						<systemProperty>
							<name>
								javax.xml.parsers.DocumentBuilderFactory
							</name>
							<value>
								com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
							</value>
						</systemProperty>
						<systemProperty>
							<name>
								javax.xml.parsers.SAXParserFactory
							</name>
							<value>
								com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
							</value>
						</systemProperty>
						<systemProperty>
							<name>
								javax.xml.transform.TransformerFactory
							</name>
							<value>
								com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
							</value>
						</systemProperty>
						<systemProperty>
							<name>org.eclipse.jetty.util.URI.charset</name>
							<value>UTF-8</value>
						</systemProperty>
					</systemProperties>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.2</version>
				<configuration>
					<archive>
						<addMavenDescriptor>false</addMavenDescriptor>
					</archive>
					<webResources>
						<resource>
							<!-- this is relative to the pom.xml directory -->
							<directory>src/main/resources/</directory>
							<targetPath>WEB-INF/classes</targetPath>
							<includes>
								<include>**/*.*</include>
							</includes>
							<filtering>true</filtering>
						</resource>
						<resource>
							<!-- this is relative to the pom.xml directory -->
							<directory>src/main/resources</directory>
							<targetPath>WEB-INF/classes</targetPath>
							<filtering>true</filtering>
						</resource>
					</webResources>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.zeroturnaround</groupId>
				<artifactId>javarebel-maven-plugin</artifactId>
				<executions>
					<execution>
						<id>generate-rebel-xml</id>
						<phase>process-resources</phase>
						<goals>
							<goal>generate</goal>
						</goals>
					</execution>
				</executions>
				<version>1.0.5</version>
			</plugin>
		</plugins>
		<pluginManagement>
			<plugins>
				<!--This plugin's configuration is used to store Eclipse m2e settings
                    only. It has no influence on the Maven build itself. -->
				<plugin>
					<groupId>org.eclipse.m2e</groupId>
					<artifactId>lifecycle-mapping</artifactId>
					<version>1.0.0</version>
					<configuration>
						<lifecycleMappingMetadata>
							<pluginExecutions>
								<pluginExecution>
									<pluginExecutionFilter>
										<groupId>
											org.zeroturnaround
										</groupId>
										<artifactId>
											javarebel-maven-plugin
										</artifactId>
										<versionRange>
											[1.0.5,)
										</versionRange>
										<goals>
											<goal>generate</goal>
										</goals>
									</pluginExecutionFilter>
									<action>
										<ignore></ignore>
									</action>
								</pluginExecution>
							</pluginExecutions>
						</lifecycleMappingMetadata>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>


</project>

谢谢大家支持,如对你有帮助,可以奉献一下你的爱心
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/GiantCrocodile/article/details/124639908