spring ioc 笔记

文件架构
config:放需要代码配置的文件
dao:放操作代码的接口文件
dao.impl:放操作代码的实现文件,关键词implements进行实现
domain:放对象实例的文件
service:放服务代码的接口文件
service.impl:放服务代码的实现文件,关键词implements进行实现,实现用到的操作可引用dao.impl
IOC使用
IOC:控制反转
用处:容器控制对象的创建
正转:我们主动控制去获取依赖对象
反转:容器来查找及注入依赖对象,对象只是被动接受依赖对象
好处:松散耦合,功能复用
代理模式,两种:
  • 1)接口代理(JDK 动态代理)
package cn.sm1234.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxyUtils {

	/**
	 * 使用JDK动态代理获取代理对象
	 * target: 目标对象
	 * @return
	 */
	public static Object getProxy(final Object target){
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(),    // 和目标对象一样的类加载器
				target.getClass().getInterfaces(), // 目标对象的接口列表
				new InvocationHandler() {
					
					//invoke: 这个方法在每次调用代理类对象的时候被执行啦!!!
					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						System.out.println("记录日志");
						
						//调用目标对象的方法(目标对象,传入参数)
						return method.invoke(target, args);
					}
				});
	}
}

  • 2)子类代理(Cglib 子类代理)

区别接口代理,直接类使用

package cn.sm1234.proxy;

import java.lang.reflect.Method;

import cn.sm1234.service.impl.CustomerServiceImpl2;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxyUtils {

	/**
	 * 使用Cglib工具创建目标对象的子类对象
	 * @param target
	 * @return
	 */
	public static Object getProxy(final Object target){
		return Enhancer.create(CustomerServiceImpl2.class, new MethodInterceptor() {
			//intercept:每次代理类对象执行方法的时候执行该方法
			@Override
			public Object intercept(Object arg0, Method method, Object[] arg2,
					MethodProxy arg3) throws Throwable {
				System.out.println("记录日志");
				//调用目标对象的方法
				return method.invoke(target, arg2);
			}
		});
	}
}

scope
scope 配置,包括:
singleton:创建一个单例的对象
prototype:每次创建一个对象(多例的)
request:用在 web 项目中,保证一个请求创建一个对象 
session: 用在 web 项目中,保证一个会话创建一个对象
scope 配置实际应用场景
1)	action 对象:必须是多例的
2)	service 对象:单例
3)	dao 对象:单例
对象生命周期方法
  1. init-method: 初始化方法
  2. destroy-method: 销毁方法
<bean id="customerDao" class="cn.sm1234.dao.impl.CustomerDaoImpl" init-method="init" destroy-method="destroy"></bean>
常用注解
@Component :创建对象(普通的 Spring 项目)
@Repository:和@Component 的作用是一样,创建对象(分层项目,Dao 层)
@Service:和@Component 的作用是一样,创建对象(分层项目,Service 层)
@Controller:和@Component 的作用是一样,创建对象(分层项目,Web 层)
@Scope:单例和多例(XML 方式里 scope 配置):@Scope("prototype")
@PostConstruct: 初始化方法
@PreDestroy:销毁方法

AppicationContext 接口,用于初始化 SpringIOC 容器。
ClassPathXmlApplicationContext: 使用类路径方式初始化 ioc 容器(推荐)
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/sm1234/test/applicationContext.xml");
FileSystemApplicationContext: 使用文件系统的方式初始化 ioc 容器
ApplicationContext ac = new FileSystemXmlApplicationContext("E:\\workspaces\\sm1234_spring\\ch01_02_spring_ioc_xml\\src\\applicationContext.xml");
ApplicationContext ac = new FileSystemXmlApplicationContext("./src/applicationContext.xml");
SpringIOC的XML方式
创建对象
<bean id="customerDao" class="cn.sm1234.dao.impl.CustomerDaoImpl"></bean>
依赖注入
构造方式参数注入
public CustomerServiceImpl(CustomerDao customerDao) {
	super();
	this.customerDao = customerDao;
}
<bean id="customerDao" class="cn.sm1234.dao.impl.CustomerDaoImpl"></bean>
<bean id="customerService" class="cn.sm1234.service.impl.CustomerServiceImpl">
    <constructor-arg index="0" ref="customerDao"/>
</bean>
setter 方法注入(推荐使用)
public CustomerServiceImpl() {
	super();
}
public void setCustomerDao(CustomerDao customerDao) {
	this.customerDao = customerDao;
}
<bean id="customerDao" class="cn.sm1234.dao.impl.CustomerDaoImpl"></bean>
<bean id="customerService" class="cn.sm1234.service.impl.CustomerServiceImpl">
    <property name="customerDao" ref="customerDao"/>
</bean>
p 名称空间注入

注意:p 名称空间简化 setter 方法注入,所以必须要有 setter 方法
p:属性 : 注入普通的数据(例如 String)
p:属性-ref:注入 JavaBean 对象(例如 CustomerDao)

xmlns:p="http://www.springframework.org/schema/p"
<bean id="customerDao" class="cn.sm1234.dao.impl.CustomerDaoImpl"></bean>
<bean id="customerService" class="cn.sm1234.service.impl.CustomerServiceImpl" p:customerDao-ref="customerDao" p:name="eric"/>
spEL 表达式注入
<bean id="customerDao" class="cn.sm1234.dao.impl.CustomerDaoImpl"></bean>
<bean id="customerService" class="cn.sm1234.service.impl.CustomerServiceImpl">
	<property name="customerDao" value="#{customerDao}"/>
	<property name="name" value="#{'eric'}"/>
</bean>
注入不同的数据类型(重点)

普通数据类型: 或者 value 属性
JavaBean 对象: 或者 ref 属性
数组:
List 集合:
Map 集合:
Properties:

//1.普通数据类型
private String gender;
public void setGender(String gender) {
	this.gender = gender;
}
//2.JavaBean类型
private Customer customer;
public void setCustomer(Customer customer) {
	this.customer = customer;
}
//3.数组类型
private String[] addresses;
public void setAddresses(String[] addresses) {
	this.addresses = addresses;
}
//4.List数组
private List<Customer> customerList;
public void setCustomerList(List<Customer> customerList) {
	this.customerList = customerList;
}
//5.Map集合
private Map<String,Customer> customerMap;
public void setCustomerMap(Map<String, Customer> customerMap) {
	this.customerMap = customerMap;
}
//6.Properties
private Properties customerProps;
public void setCustomerProps(Properties customerProps) {
	this.customerProps = customerProps;
}
	
<bean id="c1" class="cn.sm1234.domain.Customer">
	<property name="name" value="rose"/>
	<property name="gender" value="女"/>
</bean>

<bean id="c2" class="cn.sm1234.domain.Customer">
	<property name="name" value="lucy"/>
	<property name="gender" value="女"/>
</bean>

<bean id="c3" class="cn.sm1234.domain.Customer">
	<property name="name" value="lily"/>
	<property name="gender" value="女"/>
</bean>

<!-- 注入不同的数据类型 -->
<bean id="customerService" class="cn.sm1234.service.impl.CustomerServiceImpl">
	<!-- 1.普通类型 -->
	<property name="gender">
		<value>jack</value>
	</property>
	<!-- 2.JavaBean类型 -->
	<property name="customer">
		<ref bean="c1"/>
	</property>
	<!-- 3.数组类型 -->
	<property name="addresses">
		<array>
			<value>北京</value>
			<value>上海</value>
			<value>广州</value>
		</array>
	</property>
	<!-- 4.List集合 -->
	<property name="customerList">
		<list>
			<ref bean="c1"/>
			<ref bean="c2"/>
			<ref bean="c3"/>
		</list>
	</property>
	<!-- 5.Map集合 -->
	<property name="customerMap">
		<map>
			<entry key="001" value-ref="c1"/>
			<entry key="002" value-ref="c2"/>
			<entry key="003" value-ref="c3"/>
		</map>		
	</property>
	<!-- 6.Properties类型 -->
	<property name="customerProps">
		<props>
			<prop key="001">rose</prop>
			<prop key="002">eric</prop>
			<prop key="003">jack</prop>
		</props>
	</property>
</bean>
SpringIOC的注解方式
创建对象

依赖spring-aop的包,需导入
开启 springIOC 的注解功能,注意:要引入 context 的名称空间

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd

<bean id="customerDao" class="cn.sm1234.dao.impl.CustomerDaoImpl"></bean>

<!-- 加载properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 开启springIOC注解功能 -->
<!-- base-package: IOC注解的类所在包 -->
<context:component-scan base-package="cn.sm1234"/>

// 默认名称为类名(首字母小写):customerDaoImpl  
// <bean  id="customerDaoImpl" class="xxx"/>
@Component  
public class CustomerDaoImpl implements CustomerDao 
.................
依赖注入
@Value

作用:注入普通数据类型

@Value("${url}")
private String url;
@Autowired

作用:自动根据类型注入

/**
*1)自动根据类型进入注入,直接赋值给变量(无需提供构造方法或者setter方法)
*	2)如果Spring环境中没有任何一个CustomerDao的类型,那么会注入失败
*	3)如果Spring环境中出现了多个CustomerDao的类型的对象,那么也会注入失败
*/
@Autowired
private CustomerDao customerDao;
@Qualifier

作用:指定注入的对象名称
当@Autowired: 出现多个相同类型的对象的时候,可以使用@Qulifier 指定需要注入的对象名称。

@Autowired
@Qualifier(value="customerDao2") 
private CustomerDao customerDao;
@Resource

作用:既能够根据类型自动注入,也可以根据对象名称注入

@Resource(name="customerDao2") 
private CustomerDao customerDao;
  • @Autowired vs @Resource 注解的区别?
1)	注入的方式不一样:
@Autowired:只能根据类型注入,如果需要根据名称进行注入需要@Qualfier 注解的配合。
@Resource:既能够根据类型自动注入,也可以根据对象名称注入
2)	所属的标准不同
@Autowired 来自于 Spring 框架
@Resource 来自 JavaEE 标准
@Resource 注解比@Autowired 更加标准!
结论:推荐使用@Resource 注解来注入对象!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值