Java日记之spring入门

一.介绍

一款分层的一站式(full-stack)开源框架, 由持久层,WEB层…组成 , 其中两大核心技术为: IOC控制反转AOP面向切面编程.

二.基本概念

1.控制反转IOC : 谈到反转 ,那必须要提正转的概念,所谓正转 ,即A类中调用B类的方法,对象的控制权在程序员手里 ,那么显然,反转就是将对象的控制器从程序员转到spring容器中进行管理 , 具体的实现是由DI(Dependency Injction,依赖注入实现)
在这里插入图片描述
(白嫖一张图👆)

2.依赖注入 : 在运行期间由外部容器动态地将依赖对象注入容器中,注入方式在不考虑工厂模式的情况下有三种,即 : set方法注入,构造器注入,使用注解注入 , 下面会给出代码

3.AOP面向切面编程 : 这个下面会详细讲,所谓面向切面编程,就是通过预编译和动态代理的方式实现程序功能的统一维护,简单点讲,就是将于业务逻辑无关的部分代码单独划分出去

4.Bean : 在spring中,所有的对象我们都称之为Bean

三.搭建框架

1.拷贝jar包 : 选择与jdk版本匹配的jar包,版本差太大可能无法匹配
2.创建配置文件xml : 推荐的命名为applicationContext.xml
3.拷贝约束,并使用bean标签同一管理类 :

<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-4.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-4.2.xsd
	"></beans>

4.托管类 : <bean></bean>标签的id属性是唯一标识,也就是类名(当然在这里类名的首字母是小写的),class属性是类的位置

5.在主方法中加载spring配置文件,从容器中获取bean :
这里我们使用到的classpath,就是前文提到的当tomcat发布后,WEB-INF下的classes的路径

//加载配置文件
AbstractApplicationContext context = //springframework下的包
new ClassPathXmlApplicationContext("applicationContext.xml");
👆参数传递配置文件名
//获取bean
context.getBean(UserService.class);根据类型获取
UserService ud = (UserService)context.getBean("userService");根据名字获取

注 : 由于此时类是由spring管理的,默认bean为单例(也就是产出的bean的地址[哈希码]都是一样的) , 当然我们也可以通过scope属性修改为多例:scope:singleton标识对象为单例,而scope:prototype则是多例,并且可配合多线程实现一个线程一个实例

6.使用set方法注入(不唯一),需要用到property标签,name是属性名,value是属性值

7.对象的生命周期 , 这涉及到了对象的创建与销毁,我们使用getBean()方法调用初始化对象,使用context.registerShutDownHook()方法销毁对象,在队里的情况下,对象不会被销毁[只能通过GC机制销毁多例对象]
(我们也可以通过实现接口的方式进行创建销毁Bean)
代码直接在下面给出吧

四.三种注入方式

我们在前面用到了set方法注入,那么下面先给出set方法注入的代码
1.基于set()方法的注入


	public static void main(String[] args) {
		AbstractApplicationContext context = 
		new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService ud = (UserService)context.getBean("userService");
		System.out.println(ud);
		System.out.println(ud.getUsername());
		context.registerShutdownHook(); //拆卸Bean
	}

applicationContext.xml

<bean id="userService" class="com.hzyc.lesson.service.UserService" 
	init-method="myInit" destroy-method="myDestroy">
		<property name="username" value="张三" >
		<!-- set()方法注入 -->
		</property>
	</bean>
	生命周期
	public void myInit() {
		System.out.println("生命周期开始");
	}
	
	public void myDestroy() {
		System.out.println("生命周期结束");
	}

2.基于构造器的注入

<bean id="goodService" class="com.hzyc.lesson.service.GoodService" >
		<property name="goodName" value="PPP"></property>
	</bean>
	
	<bean id="userService" 
	class="com.hzyc.lesson.service.UserService">
		<constructor-arg index="0" value="zs"></constructor-arg>
		<constructor-arg index="1" ref="goodService">
		</constructor-arg>
	</bean>

注意参数与index属性的匹配

public UserService(String username, GoodService gs) {
		this.username = username;
		this.gs = gs;
	}

3.注入集合
[普通数据用value,引用数据用ref]
list (线性)

<bean id="userService" class="com.hzyc.lesson.service.UserService" >
		<property name="myList">
			<list>
				<value>长春市</value>
				<value>吉林市</value>
			</list>
		</property>
	</bean>

set (线性)

<property name="mySet">
	<set>
		<value>长春市</value>
		<value>吉林市</value>
	</set>
</property>

map (键值匹配)

<property name="myMap">
	<map>
		<entry key="1" value="长春"/>
		<entry key="2" value="吉林"/>
	</map>
</property>

property (键值匹配,跟map使用方法一样)

<property name="myProp">
	<map>
		<entry key="1" value="长春"/>
		<entry key="2" value="吉林"/>
	</map>
</property>

4.基于注解的注入
当项目中bean的数量庞大时,我们不可能一个一个去注入,而是使用标签组件扫描<context:component-scan base-package="要扫描的包"></~> ,然后再打上注解

注解 : 注解一般打在类上,使用注解后相当于在xml配置文件中使用bean注册, 类是控制器 : @controller
类是service(业务) @Service
dao层 @Responsity
无法确定类是哪一层时使用 @component
注解的作用是相同的,但是建议对应层打上对应注解提高可读性

<context:component-scan 
base-package="com.hzyc.lesson"></context:component-scan>

在一个类中注入另一个类时,这两个类都要使用 @Autowired注解,在引用的类上打上注解@Autowired
使用@Autowired注解时,如果存在接口 ,那么要把注解打在接口的实现类中
注意如果同时存在两个以上的实现类,那么系统会报错.
这个时候可以选择使用@Resource去注册或者在前者基础上增加一个@Qualifer并且使用别名去注册
代码👇

	@Autowired
	@Qualifier(value="gd1") //别名在接口的实现类中通过注解定义
	private GoodDao gd;
	@Resource(name="gd1") 写name是按名字(别名)注入
	private GoodDao gd;
	@Resource(type=GoodDaoImpl2.class) 按类型注入
	private GoodDao gd;

5.注意事项 : 当使用set方法注入的时候,需要被注入的那个类中,构造函数set()方法不能同时存在,否则会Error creating bean with name 'userService' defined in class path resource

五.生命周期的接口实现

实现InitializingBean,DisposableBean接口
public class UserService implements InitializingBean,DisposableBean{
	
	private String username;
	
	public void add() {
		System.out.println("添加...");
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("通过接口销毁");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("通过接口生成");
	}
}
去掉init和destroy属性
<bean id="userService" class="com.hzyc.lesson.service.UserService" >
	<property name="username" value="张三" >
	</property>
</bean>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值