- 降低组件之间的耦合度;
- 提供了很多服务,事务管理服务,spring core核心服务,持久化服务等等。事务管理方面,不需要我们手工控制事务,也需要手动的去处理事务的传播行为;
- 容器提供单例模式支持,不需要再编写实现代码;
- AOP技术,很容易实现权限拦截,运行期监控等功能;
- 提供了很多的辅助类,如JdbcTemplate,HibernateTemplate
- 提供了主流应用框架集成的支持,如hibernate,mybatis
- 解析配置的xml文件,获取到beans节点下面的bean
- 将bean装入集合,对外提供getBean方法,通过反射技术,Class.forName('xxx').newInstance()方法来获取到bean对象的实例
/**
* 读取xml配置文件
* @param filename
*/
private void readXML(String filename) {
SAXReader saxReader = new SAXReader();
Document document=null;
try{
URL xmlpath = this.getClass().getClassLoader().getResource(filename);
document = saxReader.read(xmlpath);
Map<String,String> nsMap = new HashMap<String,String>();
nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点
for(Element element: beans){
String id = element.attributeValue("id");//获取id属性值
String clazz = element.attributeValue("class"); //获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
XPath propertySub = element.createXPath("ns:property");
propertySub.setNamespaceURIs(nsMap);
List<Element> propertiesElement = propertySub.selectNodes(element);
for (Element property : propertiesElement) {
String name = property.attributeValue("name");
String ref = property.attributeValue("ref");
String value = property.attributeValue("value");
// System.out.println(name + "==" + ref);
beanDefine.getProperties().add(new PropertyDefinition(name, ref,value));
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 完成bean的实例化
*/
private void instanceBeans() {
for(BeanDefinition beanDefinition : beanDefines){
try {
if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
} }
/**
* 为bean对象的属性注入值
*/
private void injectObject() {
for(BeanDefinition beanDefinition : beanDefines) {
Object bean = sigletons.get(beanDefinition.getId());
try {
if(null != bean) {
//得到bean的属性集合(<bean id="personDao" class="com.test.dao.impl.PersonDaoImpl" />)
PropertyDescriptor[] pd = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();//包含class属性
for(PropertyDefinition propertyDefinition : beanDefinition.getProperties()) {//配置文件中用户定义的bean属性
for(PropertyDescriptor pDescriptor : pd) {
if(propertyDefinition.getName().equals(pDescriptor.getName())) {
Method setter = pDescriptor.getWriteMethod();//获取属性的setter方法
if(null != setter) {
Object value = null;
if(propertyDefinition.getRef() != null && !propertyDefinition.getRef().trim().equals("")) {
value = sigletons.get(propertyDefinition.getRef());
}else {
value = ConvertUtils.convert(propertyDefinition.getValues(), pDescriptor.getPropertyType());//注入基本类型的值
}
setter.setAccessible(true);//如果setter方法是private的话,invoke会报错,需要设置
setter.invoke(bean, value);//把引用对象注入到属性
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 构造函数(用的最多)
- 静态工厂
- 实例工厂
- singleton(默认):在spring ioc容器中一个bean定义只有一个实例对象,默认情况下会在容器启动的时候初始化,如果需要延迟初始化,需要在配置bean的时候加上lazy_init="true",这样只有在获取的时候才会初始化,对单个bean <bean id="person" class="com.test.bean.Person" lazy-init="true">,容器中所有bean都延迟加载<beans default-lazy-init="true">
- prototype:每次从容器获取新的bean对象 <bean id="person" class="com.test.bean.Person" scope="prototype">,在getBean的时候进行实例化
- set属性的方式注入bean:(可以被多个bean同时使用)
- 内部bean的方式注入(只可以被这一个bean使用)
- 使用构造器注入
- 使用Field注入(用于注解方式)
- 引入jar文件 common.annotations.jar
- 在xml添加配置如下
- 打开注解 <context:annotation-config />,这个配置隐式注册了多个对注释进行解析处理的处理器
- 使用@Autowired或@Resource注解方式进行装配。区别在于:@Autowired默认按类型装配,
package junit.test; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface TydicResource {
/**
* Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值:
* 1.RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略
* 2.RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略
* 3.RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用.
*
* Target(注解的作用目标)
*/
String name() default ""; }
package com.test.service.impl; import javax.annotation.Resource; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service; import junit.test.TydicResource; import com.test.dao.PersonDao;
import com.test.service.PersonService; @Service("personService") @Scope("prototype")
public class PersonServiceImpl extends Object implements PersonService { // @TydicResource(name="xgw")<!-- 注解通过name寻找到bean注入 -->
@TydicResource
// @Resource
public PersonDao personDao; public PersonDao getPersonDao() {
return personDao;
}
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
@Override
public void add() {
personDao.add();
}
}
查看set方法和field上是否加了注解
/**
* 通过注解方式注入bean
* 仿 注解处理器代码
*/
private void annotationInjectObject() {
for(String beanName : sigletons.keySet()) {
Object bean = sigletons.get(beanName);
if(null != bean) {
try {
PropertyDescriptor[] pd = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();//定义的javabean的属性集合
for(PropertyDescriptor pDescriptor : pd) {
Method setter = pDescriptor.getWriteMethod(); //属性的set方法
if(null != setter && setter.isAnnotationPresent(TydicResource.class)) {
TydicResource resource = setter.getAnnotation(TydicResource.class);//是否存在这个注解
Object value = null;
if(resource.name()!=null && !"".equals(resource.name())) {//注解中标明name属性
value = sigletons.get(resource.name());
}else {
value = sigletons.get(pDescriptor.getName());
if(value == null) { //如果在属性中也没有找到,就按类型去寻找
for(String key : sigletons.keySet()) {
/**
* isAssignableFrom
* either the same as, or is a superclass or * superinterface of, the class or interface
* 这个属性的类型如果是该磊的接口或者父类或者就是该类的话,返回true
*/
if(pDescriptor.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())) {
value = sigletons.get(key);
break;
}
}
}
}
setter.setAccessible(true);
setter.invoke(bean, value);
}
} Field[] fields = bean.getClass().getFields();
for(Field field : fields) {
TydicResource resource = field.getAnnotation(TydicResource.class);//是否存在这个注解
Object value = null;
if(resource.name()!=null && !"".equals(resource.name())) {//注解中标明name属性
value = sigletons.get(resource.name());
}else {
value = sigletons.get(field.getName());
if(value == null) { //如果在属性中也没有找到,就按类型去寻找
for(String key : sigletons.keySet()) {
if(field.getType().isAssignableFrom(sigletons.get(key).getClass())) {
value = sigletons.get(key);
break;
}
}
}
}
field.setAccessible(true);
field.set(bean, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package com.test.aop; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import com.test.service.impl.PersonServiceImpl; public class JDKProxyFactory implements InvocationHandler {
private Object targetObject; public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
PersonServiceImpl personServiceImpl = (PersonServiceImpl) this.targetObject;
Object result = null;
if(personServiceImpl.getUser()!=null) {
result = method.invoke(targetObject, args);
} return result;
}
}
package com.test.aop; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import com.test.service.impl.PersonServiceImpl; public class CglibProxyFactory implements MethodInterceptor {
private Object targetObject;//代理的目标对象 public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();//该类用于生成代理
/**
* cglib创建的代理,是目标对象的子类,能够复制非final修饰的所有方法
*/
enhancer.setSuperclass(this.targetObject.getClass());//设置父类
enhancer.setCallback(this);//设置回调用对象本身
return enhancer.create();
} @Override
public Object intercept(Object proxy, Method method, Object[] aobj,
MethodProxy methodproxy) throws Throwable {
PersonServiceImpl personServiceImpl = new PersonServiceImpl();
Object result = null;
if(personServiceImpl.getUser() != null) {
result = methodproxy.invoke(targetObject, aobj);
}
return result;
} }
- 引入命名空间
- 直接配置在spring的配置文件中
- 配置在配置文件(db.properties)中
Spring框架的初步学习的更多相关文章
-
Spring框架-AOP详细学习[转载]
参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...
-
Spring框架零基础学习(一):IOC|DI、AOP
文章目录 一.IDEA创建Spring项目 二.Spring: IOC和DI 三.Spring: AOP 参考链接: HOW2J.CN:Spring idea创建一个spring项目 一.IDEA创建 ...
-
学习Spring框架等技术的方向、方法和动机
学习Spring框架最早学习Spring框架是在大二的时候,当时看了几本书,看了一些视频,主要是传智播客的.更多的,还是写代码,单独写Spring的,也有与Struts和Hibernate等框架整合的 ...
-
Spring框架学习一
Spring框架学习,转自http://blog.csdn.net/lishuangzhe7047/article/details/20740209 Spring框架学习(一) 1.什么是Spring ...
-
老周的ABP框架系列教程 -》 一、框架理论初步学习
老周的ABP框架系列教程 -- 一.框架理论初步学习 1. ABP框架的来源与作用简介 1.1 简介 1.1.1 ABP框架全称为"ASP.NET Boilerplate ...
-
Spring框架学习之第2节
传统的方法和使用spring的方法 使用spring,没有new对象,我们把创建对象的任务交给了spring的框架,通过配置用时get一下就行. 项目结构 applicationContext.xml ...
-
Spring框架学习 - 配置
[资料] ★★☆ Spring 中提供一些Aware相关接口,像是BeanFactoryAware. ApplicationContextAware.ResourceLoaderAware.Servl ...
-
深入浅出学习Spring框架(四):IoC和AOP的应用——事务配置
在前文 深入浅出学习Spring框架(一):通过Demo阐述IoC和DI的优势所在. 深入浅出学习Spring框架(三):AOP 详解 分别介绍了Spring的核心功能——IoC和AOP,光讲知识远远 ...
-
spring框架学习(三)junit单元测试
spring框架学习(三)junit单元测试 单元测试不是头一次听说了,但只是听说从来没有用过.一个模块怎么测试呢,是不是得专门为一单元写一个测试程序,然后将测试单元代码拿过来测试? 我是这么想的.学 ...
随机推荐
-
关于favicon.ico,shortcut icon,icon
引入一篇文章.关于favicon.ico二三事. http://www.cnblogs.com/LoveJenny/archive/2012/05/22/2512683.html 一直对favicon ...
-
appium + python 环境搭建
所需:JDK.Android SDK.Appium服务程序.Appium客户端程序 1. 安装最新的JDK,并配置环境变量. JAVA_HOME=C:\Program Files (x86)\Java ...
-
3.SRS文档
1.功能需求 本程序的使用者为局域网用户.程序实现的主要功能是局域网的常见格式的文件的传 输.其用例图如图1.本程序可通过可视化操作界面实现一对多的文件传输. 1.1模块分析 为实现局域网文件传输, ...
-
Contains Duplicate II 解答
Question Given an array of integers and an integer k, find out whether there are two distinct indice ...
-
在VisualStudio中显示当前的分支名
当项目多的时候,当分支多的时候,当会议多的时候. 你打开VS,你是否犹豫过,"我现在是打开的哪个分支?!!!!??!" 如果你米有犹豫过,是否有过,"FXXXXK, 我怎 ...
-
iOS-桥接方式
很多时候都会使用到CoreFoundation的函数,其返回值为CoreFoundation框架的对象,如果想转换为Foundation框架的对象就可以使用桥接方式来搞定. 示例代码: CFStrin ...
-
201521123119《Java程序设计》第7周学习总结
1. 本周学习总结 2. 书面作业 Q1.ArrayList代码分析 Q1.1 解释ArrayList的contains源代码 这段代码的主要目的是判断在对ArrayList遍历时所用的方法,在输入参 ...
-
ReentrantLock 实现原理
使用 synchronize 来做同步处理时,锁的获取和释放都是隐式的,实现的原理是通过编译后加上不同的机器指令来实现. 而 ReentrantLock 就是一个普通的类,它是基于 AQS(Abstr ...
-
【Java每日一题】20170117
20170116问题解析请点击今日问题下方的“[Java每日一题]20170117”查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; import jav ...
-
layui table动态表头 改变表格头部 重新加载表格
改变头部原理: 删除原来表格, 重新建立DOM元素, 重新加载table,实现表头改变 明白了原理, 我相信大家都能写出来了, table.reload(ID, options)目前好像还不支持con ...