Spring框架学习笔记

1. Spring

Spring的核心要素有两点,ioc(Inversion of Control)aop(Aspect Oriented Programmin),即控制反转面向切面编程

1.1 控制反转(IOC)

Spring框架能够提供对程序中对象的创建、赋值和管理,而不需要我们手动去创建对象,IOC的底层采用的是反射机制,Servlet就是一种IOC的体现,在Servlet程序中,我们并没有创建过Servlet对象,而全部都是由Tomcat服务器提供对Servlet的创建、管理和销毁等操作,我们只需要专注于业务逻辑的实现,简化开发流程。

开发流程

  1. 配置pom.xml文件,加入spring框架各个组件的坐标
  2. 编写spring配置文件applicationContext.xml,放置于resources目录中
  3. 在spring配置文件中加入各个组件bean
  4. 实现文件中可以对直接对bean进行调用

示例
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" 
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!--在spring配置文件中配置所需要的bean-->
	<!--
		id是所需要的类对象的唯一标识
		class代表id所对应的类的全限定类名
	-->
	<bean id="userDao" class="com.xxx.xxx.UserDaoImpl"></bean>

这样配置之后就可以使用该类的实例对象,使用方法为:

public static void main(String[] args){
	// 通过spring的核心配置文件来加载其中定义的bean
	ApplicationContext app = new ClassPathXmlApplicationContext('applicationContext');
	// 以id为参数来获取对应的类对象
	UserDao userDao = (UserDao)app.getBean('userDao');
	// 可以调用userDao的方法
	//...
}

在Spring中,框架采用反射机制,默认使用bean的无参构造方法来创建实例,在配置bean时,可以指定bean的作用范围,通常有singletonprototype两种方式,方式的写法如下:

<bean id="userDao" class="com.xxx.xxx.UserDaoImpl" scope="singleton"></bean>

这两种方法的区别如下表,Spring默认创建是singleton

参数作用作用范围
singleton框架中只包含一个实例在读取主配置文件时就创建对象
prototype框架中可以包含多个实例调用一次getBean方法就创建一个新对象

在创建Bean实例时,可以指定方法来指定bean进行初始化init或者销毁时的动作

<bean id="userDao" class="com.xxx.xxx.UserDaoImpl" init-method="init" destory-method="destory"></bean>

同时需要在userDao的类中添加对应名称的方法

public class UserDaoImpl {
	public void init(){
		// do some...
	}
	public void destory(){
		// do some...
	}
}

最后,Bean的实例化方式除了无参构造方法以外,还有两种方法

  1. 工厂静态方法实例化
  2. 工厂实例方法实例化

在这两种方法中,需要实现bean的工厂类,并在工厂中定义实例创建的方法,同时需要在Spring的配置文件applicationContext.xml文件中添加工厂的bean,并在其中添加属性factory-method,采用工厂中的方法来构造实例

如果是静态工厂方法,那么只需要实现一个工厂类,调用其中的静态方法;但如果是工厂实例方法,那么需要先生成一个工厂的bean,再在其中调用工厂中的方法。

1.2 依赖注入(DI)

1.2.1 引用类型依赖注入

想在某个类,比如UserService类中注入UserDao类的对象(UserService类中有UserDao类的实例),有以下几种方法(在框架的层面实现注入而不需要进入到代码中):

1)set方法注入
<bean id="userDao" class="com.xxx.xxx.UserDaoImpl"></bean>
<bean id="userService" class="com.xxx.xxx.UserServiceImpl">
	<!--
	第一个name是UserService类中setUserDao()方法的set后面的名称
	第二个ref属性代表这个引用了上方id为userDao的bean来进行注入
	-->
	<property name="userDao" ref="userDao"></property>
</bean>
2)有参构造器注入

这个方法需要在UserService类中提供一个有参构造方法

public class UserService{
	private UserDao userDao;
	// constructor
	public UserService(UserDao userDao){
		this.userDao = userDao;
	}
	// other method...
}

然后配置主配置文件

<bean id="userDao" class="com.xxx.xxx.UserDaoImpl"></bean>
<bean id="userService" class="com.xxx.xxx.UserServiceImpl">
	<!--
	第一个name是UserService类中构造方法的参数名
	第二个ref属性代表这个引用了上方id为userDao的bean来进行注入
	-->
	<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>

1.2.2 普通数据类型依赖注入

public class UserService{
	private String userName;
	private int age;
	// getter and setter method...
}
<bean id="userService" class="com.xxx.xxx.UserServiceImpl">
	<property name="userName" value="zhangsan"></property>
	<property name="age" value="18"></property>
</bean>

1.2.3 集合类型依赖注入

public class UserService{
	private List<String> strLists;
	private Map<String, User> userMap;
	// getter and setter method...
}
public class User{
	private String userName;
	private int age;
	// getter and setter method...
}
<!--user对象,用于依赖注入到map的value中-->
<bean id="userOne" class="com.xxx.xxx.User">
	<property name="userName" value="zhangsan"></property>
	<property name="age" value="18"></property>
</bean>

<bean id="userTwo" class="com.xxx.xxx.User">
	<property name="userName" value="lisi"></property>
	<property name="age" value="28"></property>
</bean>

<bean id="userService" class="com.xxx.xxx.UserServiceImpl">
	<property name="strLists">
		<list>
			<value>aaa</value>
			<value>bbb</value>
			<value>ccc</value>
		</list>
	</property>
	<property name="userMap">
		<map>
			<entry key="userone" value-ref="userOne"></entry>
			<entry key="usertwo" value-ref="userTwo"></entry>
		</map>
	</property>
</bean>

1.2.4 配置数据库连接池

采用alibaba的Druid数据库连接池,在spring的主配置文件中配置如下,同时还需要在pom.xml文件中引入各个依赖项的坐标

	<!--加载外部的properties文件-->
	<context:property-placeholder location="classpath:jdbc.properties"/>

	<!--数据库连接池配置 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close" lazy-init="false">
        <!--以下是各项配置参数的设置-->
        <!--属性可以在jdbc.properties配置文件中读取-->
        <!--property后面的name是setter方法的set后面的那个属性名-->
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="initialSize" value="1" />
        <property name="maxActive" value="50" />
        <property name="maxWait" value="30000" />
 
        <property name="filters" value="stat,wall" />
        <property name="timeBetweenEvictionRunsMillis" value="3000" />
        <property name="minEvictableIdleTimeMillis" value="300000" />
        <property name="validationQuery" value="SELECT 'x'" />
    </bean>    

1.3 注解(Annotation)

使用注解可以大大减少配置xml文件的工作,简化开发流程

1.3.1 原始注解

注解说明
@Component在类上标注用于实例化Bean
@Controller使用在web项目中的controller层类上实例化Bean
@Service使用在web项目中的service层类上实例化Bean
@Repository使用在web项目中的dao层类上实例化Bean
@Autowired使用在字段上用于类型注入(Spring会根据字段类型去寻找对应的bean注入)
@Qulifier配合@Autowired一起使用,使得@Autowired可以根据名称进行注入,一般写为@Qulifier("xxx")
@Resource相当于@Qulifier+@Autowired,依照名称进行注入
@Value对普通类型注入属性,通常用于配置文件的读取注入参数@Value(${xxx})
@Scope标注Bean的作用范围,一般用在类上,常用@Scope("singleton")或者@Scope("prototype")
@PostConstruct使用在方法上标注该方法是Bean的初始化方法,通常用于init()方法
@PreDestory使用在方法上标注该方法是Bean的销毁方法

下面的几个类给出了一些常用的方式

// 业务逻辑层,根据请求实现特定的逻辑
@Service
public class MusicServiceImpl implements MusicService {
    @Autowired
    private MusicDao musicDao;

    @Override
    public int addMusic(Music music) {
        int result = musicDao.insertMusic(music);
        return result;
    }

    @Override
    public List<Music> findMusics() {
        return musicDao.selectMusics();
    }
}

// web层,处理请求,调用相应的service
@Controller
public class MusicController {
    @Resource
    private MusicService musicService;

    // 添加音乐
    @RequestMapping("/addMusic.do")
    public ModelAndView addMusic(Music music){
        ModelAndView mv = new ModelAndView();
        String tips = "注册失败";
        // 调用service处理添加音乐
        int res = musicService.addMusic(music);
        if(res > 0){
            tips = "音乐【" + music.getName() + "】添加成功";
        }
        // 结果页面
        mv.addObject("tips", tips);
        // 指定结果页面
        mv.setViewName("result");
        return mv;
    }
}

但是使用上面的这些注解,只能够注解我们自定义的一些类,对于一些不是我们自定义的第三方类,就束手无策了,例如alibaba的druid数据库连接池,如果使用上面的注解方式,就必须找到druid连接池的源码并在上面进行注解,这显然不现实,那么为了完全替代xml配置文件,需要使用到一些新的注解。

1.3.2 新注解

注解说明
@Configuration用于指定当前类是一个Spring核心配置类,当创建容器时会从该类上进行注解的加载
@ComponentScan用于指定Spring在初始化容器时需要扫描的包
@Bean用在方法上,将方法的返回值存储到Spring容器中
@PropertySource用于加载.properties配置文件中的信息
@Import用于导入其他的配置类

示例代码

// 核心配置类

// 标志该类是Spring的核心配置类
@Configuration
// 组件扫描器,扫描参数所对应的包
@ComponentScan("com.xxx.xxx")
// 加载数据库连接池的配置
@Import({DataSourceConfiguration.class, xxx.class})
public class SpringConfiguration{
}
// 数据库连接池配置

@PropertySource("classpath:xxx") // 读取配置文件
public class DataSourceConfiguration{
@Value("${jdbc.driver}") // 读取配置文件中的信息,解耦合
	private String driverClass;
	// 其余配置文件信息...

	@Bean("xxx") // 参数为对象在容器中的名称,Spring会将当前方法的返回值以xxx的名称存储在容器中
	public DataSource getDataSource(){
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setDriverClass(driverClass);
		// 其余设置项...
		
		return dataSource;
	}
}

那么在main函数中的写法变为了

public static void main(String[] args){
	ApplicationContext app = new AnnotationConfigurationContext(SpringConfiguration.class);
	xxx cls = app.getBean(xxx.class);
	cls.method();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值