Spring 初级入门

核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。可以将一些通用任务,如安全、事务、日志等集中进行管理,提高了复用性和管理的便捷性。

Spring DAO:为JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

1、工厂模式初见:

在以往java开发时,我们想要创建对象都是直接new,业务层调用持久层时,就需要在业务层new出持久层的对象,增加两层的耦合

//        工厂方法解耦 java代码实现思路
//        业务层
//        A接口      定义业务方法名
//        D实现类  实现A接口方法
//
//        持久层
//        B接口      定义持久方法名
//        F实现类  实现B接口方法
//
//        D、F通过工厂方法创建对象,然后用用接口指向对应生成的对象,仅仅通过接口实现对应的方法互相调用,而具体的实现类则被解耦,在编译时,就算实现类被删除不存在也不会产生错误

2、spring基础模式

xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--    id spring通过id找到class 通过反射找到该类 scope对象创建模式 singleton单例 prototype多例 request session globalsession-->
<!--    默认使用class的构造函数来创建对象-->
    <bean id="example" class="com.mobao.singleton.User" scope="prototype">
<!--        调用构造函数并传参 name用来指定参数的名称-->
        <constructor-arg name="name" value="名字"></constructor-arg>
        <constructor-arg name="age" value="19"></constructor-arg>

<!--        如果传入的参数为其他的对象类型,则需要用ref来引用同在spring容器内的对象-->
        <constructor-arg name="birthday" ref="dateobj"></constructor-arg>
    </bean>
<!--    作为参数被引用的数据类型对象-->
    <bean id="dateobj" class="java.util.Date">
    </bean>

<!--    使用默认构造函数创建对象,set方法注入参数-->
    <bean id="listinjection" class="com.mobao.singleton.User">
<!--        参数注入-->
<!--        <constructor-arg name="name" value="名字"></constructor-arg>-->

<!--        set方法注入-->
        <property name="name" value="set方法注入"></property>
    </bean>

<!--        set方法注入集合属性-->
    <bean id="mapinjection" class="com.mobao.singleton.User">
        <property name="student">
<!--            list类-->
            <list>
                <value>1</value>
                <value>2</value>
            </list>
<!--            <array>-->
<!--                <value>1</value>-->
<!--                <value>2</value>-->
<!--            </array>-->
<!--            <set>-->
<!--                <value>1</value>-->
<!--                <value>2</value>-->
<!--            </set>-->
        </property>
        <property name="studentmap">
<!--            map类-->
            <props>
                <prop key="key">value</prop>
                <prop key="key2">value2</prop>
            </props>
<!--            <map>-->
<!--                <entry key="key" value="value"></entry>-->
<!--                <entry key="key2" value="value2"></entry>-->
<!--            </map>-->
        </property>
    </bean>

<!--    public class User {-->

<!--    private String name;-->
<!--    private Integer age;-->
<!--    private Date birthday;-->

<!--    public String getName() {-->
<!--    return name;-->
<!--    }-->

<!--    public void setName(String name) {-->
<!--    this.name = name;-->
<!--    }-->

<!--    public Integer getAge() {-->
<!--    return age;-->
<!--    }-->

<!--    public void setAge(Integer age) {-->
<!--    this.age = age;-->
<!--    }-->

<!--    public Date getBirthday() {-->
<!--    return birthday;-->
<!--    }-->

<!--    public void setBirthday(Date birthday) {-->
<!--    this.birthday = birthday;-->
<!--    }-->

<!--    @Override-->
<!--    public String toString() {-->
<!--    return "User{" +-->
<!--    "name='" + name + '\'' +-->
<!--    ", age=" + age +-->
<!--    ", birthday=" + birthday +-->
<!--    '}';-->
<!--    }-->

<!--    public void test() {-->
<!--    System.out.println("nihaoya == " + this);-->
<!--    }-->

<!--    public User() {-->
<!--    System.out.println("构造 user");-->
<!--    }-->

<!--    public User(String name, Integer age, Date birthday){-->
<!--    this.name = name;-->
<!--    this.age = age;-->
<!--    this.birthday = birthday;-->
<!--    }-->

<!--    }-->

<!--    id为映射字符串 class为映射到指定的类 无其他参数指定类创建的方式默认使用默认构造函数
注:java中如果实现了构造函数(带参)默认的构造函数则失效-->
    <bean id="userspring" class="com.mobao.singleton.User"></bean>

<!--    public class UserFactory {-->

<!--    public User returnUser(){-->
<!--    System.out.println("调用工厂类指定方法返回值");-->
<!--    return new User();-->
<!--    }-->

<!--    通过调用指定的方法返回指定的对象(创建id为usersping2的对象)
factory-bean    指定调用工厂类
factory-method  指定调用工厂类的方法
-->
    <bean id="userfactory" class="com.mobao.singleton.UserFactory"></bean>
    <bean id="usersping2" factory-bean="userfactory" factory-method="returnUser"></bean>

<!--    public class UserStaticFactory {-->
<!--    public static User returnUser(){-->
<!--    System.out.println("调用工厂类的静态方法返回对象");-->
<!--    return new User();-->
<!--    }-->
<!--    }-->

<!--    直接使用工厂类的静态方法返回指定对象-->
    <bean id="userstatic" class="com.mobao.singleton.UserStaticFactory" factory-method="returnUser"></bean>

</beans>

java代码:

//        1、根据核心容器获取对象,配置文件读取后,对象即被创建出来
//        FileSystemXmlApplicationContext       获取本地磁盘下的文件
//        ClassPathXmlApplicationContext        获取类路径下文件
//        AnnotationConfigApplicationContext

        //配置文件读取后,对象即被创建出来
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

//        直接使用构造方法创建对象
        User user = (User) ac.getBean("userspring");
        user.test();
        User user2 = (User) ac.getBean("userspring");
        user2.test();

//        使用工厂类的方法返回对象
        User factoryMethodUser = (User)ac.getBean("usersping2");

//        使用工厂类的静态方法返回对象
        User staticfactoryMethodUser = (User)ac.getBean("userstatic");


//        2、根据BeanFactory获取对象
        Resource resource = new ClassPathResource("bean.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        User beanfactoryUser = (User)beanFactory.getBean("userspring");
        beanfactoryUser.test();
        User beanfactoryUser2 = (User)beanFactory.getBean("userspring");
        beanfactoryUser2.test();

总结:

<!--    使用默认构造函数创建对象,set方法注入参数-->
    <bean id="userset" class="com.mobao.singleton.User">
<!--        参数注入-->
<!--        <constructor-arg name="name" value="名字"></constructor-arg>-->

<!--        set方法注入-->
        <property name="name" value="set方法注入"></property>
    </bean>

<!--        set方法注入集合属性-->
    <bean id="mapinjection" class="com.mobao.singleton.User">
        <property name="student">
            <list>
                <value>1</value>
                <value>2</value>
            </list>
<!--            <array>-->
<!--                <value>1</value>-->
<!--                <value>2</value>-->
<!--            </array>-->
<!--            <set>-->
<!--                <value>1</value>-->
<!--                <value>2</value>-->
<!--            </set>-->
        </property>
    </bean>

3、spring注解模式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!--    base-package指定包目录,扫描该目录下的所有含有注解@Component的类-->
    <context:component-scan base-package="com.mobao.springannotation"></context:component-scan>

</beans>

java类声明

//指定id为指定字符串
//@Component(value = "annotation")
//默认id为类名第一字母小写
//通用
@Component
//表现层
@Controller
//服务层
@Service
//持久层
@Repository
public class SpringAnnotation {
    public SpringAnnotation(){
        System.out.println("对象被创建了");
    }
}

成员属性注入(存在的问题,使用注解注入成员属性,不方便传参,如果成员属性是另一个bean对象,因为是@Autowired,不方便用指定的参数注入这个bean对象)

//指定id为指定字符串
//@Component(value = "annotation")
//默认id为类名第一字母小写
//通用
@Component
////表现层
//@Controller
////服务层
//@Service
////持久层
//@Repository

//singleton单例 prototype多例
@Scope("singleton")

public class SpringAnnotation {
//    有唯一的bean对象类型和要注入的数据相同,则注入成功
//    注入逻辑 IOC是map接口 beanid为key value为类
//    @Autowired 先根据类的类型去IOC的map结构中查找相同类型的类,如果类是唯一的则直接注入,
//    如果有多个类(包括接口被多个类实现、类被多个子类继承均为多个类!!!),则拿变量名作为beanid,继续在同类型的类中,找到beanid相同的类进行注入
    @Autowired
//    public AutowiredValue autowiredValue;
    public AutowiredValue autowiredValueSon;

//    但是如果有多个类,变量名我们又想任意去取时,这时候我们要再加入一个注入指明注入的beanid
    @Autowired
    @Qualifier("autowiredValueSon")
    public AutowiredValue aaaaa;

//    基本数据类型和String类型数据的注入
    @Value("66666")
    public String bbbb;

    public SpringAnnotation(){
        System.out.println("对象被创建了");
    }
}

4、spring新注解(摒弃繁重的xml文件 将配置换为类)

知识点①,@Bean(name = "BinSpring"),用于方法上的注解,对方法返回值进行beanid的管理,原来的注解配置本来是要在每个类前面加入注解,导致注解非常分散,不易管理,有了该注解,就可以将注解集中起来,通过方法回调为对象加入注解,并且我们可以在这个地方很方便地进行传参
注:之前的@Component注解属于类注解,直接作用于类名上,缺点就是分散

    @Bean(name = "BinSpring")
    public BinSpring createBinSpring(){
        return new BinSpring();
    }

将类注解为配置文件,替换xml

//声明该类为配置类
@Configuration
//扫描注解范围,如果不想通过@Bean统一管理,则还是按原来的在类上进行注解,则需要配置scan,才能正常使用
@ComponentScan("com.momi")

public class ConfigClass {

//    通过@Bean统一管理
    @Bean(name = "binSpring")
    @Scope("singleton")
    public BinSpring createBinSpring(){
        return new BinSpring();
    }

    @Bean(name = "binBean")
    @Scope("prototype")
    public BinBean createBinBean(){
        return new BinBean();
    }
}
AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(ConfigClass.class);

BinBean binBean = (BinBean) acac.getBean("binBean");
BinSpring binSpring = (BinSpring) acac.getBean("binSpring");

随着工程越做越大,我们对应的config类代码也会原来越多,那么就需要进行进一步的分解,使用多个config类,比如aconfig负责业务层,bconfig负责服务层...

//声明该类为配置类
@Configuration
//扫描注解范围,如果不想通过@Bean统一管理,则还是按原来的在类上进行注解,则需要配置scan,才能正常使用
@ComponentScan("com.momi")
//导入另一个配置类
@Import(ConfigB.class)
public class ConfigClass {

//    通过@Bean统一管理
    @Bean(name = "binSpring")
    @Scope("singleton")
    public BinSpring createBinSpring(){
        return new BinSpring();
    }

    @Bean(name = "binBean")
    @Scope("prototype")
    public BinBean createBinBean(){
        return new BinBean();
    }
}
public class CBean {
    public CBean(){
        System.out.println("CBean 创建了" + this);
    }
}
@Configuration
public class ConfigB {

    @Bean(name = "cbean")
    @Scope("prototype")
    public CBean createCBean(){
        return new CBean();
    }

}

5、注解模式获取property文件数据

(to do...
@PropertySource 获取property文件的路径问题 )
在config类中,添加@PropertySource("classpath:values.properties")

@Configuration
@PropertySource("classpath:values.properties")
    public class ConfigB {

    @Bean(name = "cbean")
    @Scope("prototype")
    public CBean createCBean(){
        return new CBean();
    }

}

在对象类中结合@Value实现数据注入

public class CBean {
//    @Value用户String和基本数据注入
    @Value("${name}")
    private String name;
    @Value("${password}")
    private Integer password;
    @Value("${age}")
    public Integer age;

    public CBean(){
        System.out.println("CBean 创建了" + this);
    }
}

5-1、使用配置类,如何实现xml文件配置的ref功能,即一个类创建需要另一个类作为参数

@Configuration
@PropertySource("classpath:values.properties")
public class ConfigB {

    @Bean(name = "cbean")
    @Scope("prototype")
//    这里的 CBeanPara cBeanPara 参数自动注入依照类似autowired规则进行注入 先匹配类型,有同样类型的匹配用变量名匹配bean名/使用Qualifier指定bean名
//    注:先去查类型为CBeanPara的bean对象,如果有多个则使用cbpara 去匹配bean名(value)/或者使用使用Qualifier直接指定bean名
    public CBean createCBean(@Qualifier("para1") CBeanPara cbpara) {
        return new CBean();
    }

    @Bean(value = "para1")
    @Scope(value = "prototype")
    public CBeanPara createPara(){
        CBeanPara cBeanPara = new CBeanPara();
        System.out.println("使用了 para1" + cBeanPara);
        return cBeanPara;
    }

    @Bean(value = "para2")
    @Scope(value = "prototype")
    public CBeanPara createPara2(){
        CBeanPara cBeanPara = new CBeanPara();
        System.out.println("使用了 para2" + cBeanPara);
        return cBeanPara;
    }
}

5-2、spring自身提供方便junit进行测试的注解

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.1.RELEASE</version>
            <scope>test</scope>
        </dependency>

起因:在单元测试的时候,如何省去实例化对象过程

//以下两行注解相当于自动将配置导入和示例化
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ConfigClass.class)

在test文件夹下的测试类配置如下注解

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ConfigClass.class)
public class SpringJunit {

    @Autowired
    CBean bean;

    @Autowired
    @Qualifier("para2")
    CBeanPara cBeanPara;

    @Test
    public void test() {
        System.out.println("测试" + bean);
    }
    
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容