2、spring的第二种注入方法:基于构造方法完成对属性值的注入
<bean id="user" class="com.jy.beans.User"><!--通过构造注入数据--><constructor-arg name="name" value="dnflaksd"></constructor-arg><constructor-arg name="date" ref="date"></constructor-arg></bean><bean id="date" class="java.util.Date"></bean>
七、关于组件的生命周期
a.组件的作用范围是单例:组件会随着容器的销毁而销毁。
b.组件的作用范围是多例:容器销毁时,组件不会销毁,会由垃圾回收机制回收。
八、模拟spring底层基于工厂模式解耦
首先程序会读取配置文件,获取文件中的全类名数据,根据反射创建对象(单例),保存在容器中,后面如果有用到实例的地方,我们从容器中获取。
beans.properties
caseServlet = com.jy.factory.servlet.CaseServletcaseService = com.jy.factory.service.CaseServiceImplcaseDao = com.jy.factory.dao.CaseDaoImpl
BeanFactory:
public class BeanFactory {/*** 模拟一个容器*/private static Map beansMap;private static Properties properties;/*** 在静态代码块中创建容器对象,是为了保证存入容器中的实例是单例的,所有的存放实例的步骤,* 也要在类加载的时候完成*/static {//实例化容器beansMap = new HashMap();//实例化properties集合properties = new Properties();FileReader fileReader = null;//读取配置文件try {fileReader = new FileReader("src/beans.properties");//读取数据到集合properties.load(fileReader);//获取properties中所有的keyEnumeration keys = properties.keys();//遍历所有的keywhile (keys.hasMoreElements()){//先获取对应key的字符串String s = keys.nextElement().toString();//根据key获取valueString propertyClass = properties.getProperty(s);//根据反射创建对象Object value = Class.forName(propertyClass).newInstance();//将实例存到容器里beansMap.put(s,value);}} catch (Exception e) {e.printStackTrace();} finally {try {fileReader.close();} catch (IOException e) {e.printStackTrace();}}}/*** 定义一个获取实例的方法*/public static Object getBean(String beanName){//从集合中获取实例Object o = beansMap.get(beanName);return o;}}
持久层:CaseDaoImpl
public class CaseDaoImpl implements CaseDao{@Overridepublic void getMethod() {System.out.println("持久层数据");}}
业务层:CaseServiceImpl
public class CaseServiceImpl implements CaseService{@Overridepublic void getMethod() {CaseDao caseDao = (CaseDao)BeanFactory.getBean("caseDao");caseDao.getMethod();}}
表现层:CaseServlet
public class CaseServlet {public void getMethod(){/*** 从工厂中获取实例*/CaseService caseService = (CaseService)BeanFactory.getBean("caseService");caseService.getMethod();}}
测试:
public static void main(String[] args) {//从自定义工厂对象中获取表现层实例CaseServlet caseServlet = (CaseServlet)BeanFactory.getBean("caseServlet");caseServlet.getMethod();}
九、基于注解的IOC配置
1、在配置文件上开启spring对注解的支持
<!--开启spring对注解的支持:其实就是一个扫描包的过程spring程序在执行的时候会解析配置文件的数据,找到对应的包结构,并扫描该包下面的子包,然后回去检测每个类上有没有spring提供的注解,如果有,会将该类的实例装载进spring容器中--><context:component-scan base-package="com.jy"></context:component-scan>
2、在类上加上对应的注解
四个注解作用一样:
@Component:把资源让spring来管理,相当于在xml中配置一个bean
@Controller:一般用于表现层的注解
@Service:一般用于业务层的注解
@Repository:一般用于持久层的注解
@Componentpublic class Student {}/***核心容器对象获取实例时,其标识(参数)默认为首字母小写的类名*/public static void main(String[] args) {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("xml/beans2.xml");Object user = classPathXmlApplicationContext.getBean("student");System.out.println(user);}
四个注解都可以自定义标识
@Component("sss")public class Student {}/***核心容器对象获取实例时,其标识(参数)默认为首字母小写的类名*/public static void main(String[] args) {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("xml/beans2.xml");Object user = classPathXmlApplicationContext.getBean("sss");System.out.println(user);}
@Scope:可以改变bean的作用范围
如:@Scope(“prototype”)
生命周期相关:
@PostConstruct:用于指定初始化的方法
@PreDestroy:用于指定销毁的方法
@Component@Scope("prototype")public class Student {@PostConstructpublic void initMethod(){System.out.println("初始化的方法");}@PreDestroypublic void destroyMethod(){System.out.println("销毁的方法");}}
用于注入数据的注解:
@Autowired(根据类型注入):
注入流程:spring扫描到属性上有该注解后,会去容器中找到该属性对应的类型与之注入。
如果spring容器中与该属性类型匹配的有多个,比如一个接口有多个实现类,实现类都采用了注解的默认值,那么究竟该注入哪个实例?
这种情况下程序会报错!
解决方案:
1、给这个类起标识, 标识要和被注入属性的属性名相同。

2、与Qualifier结合使用,由Qualifier来决定注入哪个实例。
@Qualifier(不能单独使用):只能和Autowired结合使用
@Resource(根据id注入的)
@Value(用于注入基本数据类型和String类型):支持el表达式。不能直接注入静态属性。
