2:DI:依赖注入,在运行期,由外部容器动态的将依赖对象注入到组件中,可以通过构造函数的参数形式注入,也可以通过set方法注入。
3:为何要使用Spring
a.降低组件之间的耦合度,实现软件各层之间的解耦
Controller---Service---Dao
b.可以使用容器提供的各种服务,不需要处理复杂的事物传播行为
事务管理
c.容器提供单例模式,开发人员不需要自己编写实现代码
d.容器提供AOP技术,利用它很容易实现如权限拦截,运行期监控等功能。
e.容器提供了众多的辅佐类,使用这些类能够加快应用的开发,
如:jdbcTemplate、HibernateTemplate.
d.Spring对于主流的应用框架提供了集成支持,
如:集成hibernate、JPA、Structs 等,这样更便于应用的开发
4:轻量级与重量级概念的划分
主要看它使用了多少服务
如何使用spring?
使用spring需要的jar包
添加配置文件beans.xml,加入<bean id = "" class = "需要注入的类的路径"></bean>
ApplicationContext ctx =
new ClassPathXmlApplicationContext(String []{"beans.xml"})
ctx.getBean("配置文件中需注入类的class属性")
这样就可以得到我们所依赖的对象了,这个依赖对象由spring帮我们管理
Spring是如何读取beans.xml的?
Bean的作用域
scope=""
1.singleton 默认
容器实例化时对象被实例化,只创建一个对象
2.pototype
调用getBean()方法时被实例化,每次都会创建一个新对象
我们可以延迟实例化
在<bean>中加上 lazy-init = "true"
如果我们要将所有的bean都延迟实例化 就在<beans>中加入
default-lazy-init = "true"
如果需要当<bean>被实例化时就执行方法 就在<bean>中加入init-method = "方法名"
看一个对象是否被实例化,在他的默认构造方法中输出一句话 看看构造方法是否被调用
当我们需要关闭容器时执行某个方法,在bean中加入 destroy-method="方法名"
使用setter方法进行注入:
要将service层和dao层彻底解耦,我们需要将dao实现类所实现的接口直接注入到service
层,然后提供set、get方法,直接可以用注入的接口调用方法,在beans.xml中注入接口
的实现类,然后将它注入到service层的bean中作为属性,
<property name="personDao1" ref="personDao1" ></property>
name="属性名"
事实上是:先将PersonDaoBean注入到spring容器中,然后再将注入到spring容器中的
PersonDaoBean作为属性注入到PersonServiceBean中作为属性,命名为personDao,事实
上personDao本来就是PersonServiceBean的属性,所以啊,通过这么一来 就把
PersonDaoBean注入到PersonServiceBean中了 ,那么这时候PersonServiceBean
通过personDao就可以调用PersonDaoBean中的方法了。如此而已。 注意哦:这样注入就不要再提供带参构造方法了!!!
例子:
1 <bean id = "studentDao" class = "Student.Dao.Impl.StudentDaoImpl"></bean> 2 <bean id = "studentServiceBean" class = "Student.Service.StudentServiceBean"> 3 <property name="studentDao" ref="studentDao"></property> 4 </bean>
还可以使用内部Bean方式为属性注入值,但不能被其他调用
像这样:
1 <property name="studentDao"> 2 <bean class="Student.Dao.Impl.StudentDaoImpl"/> 3 </property>
注入基本类型:<property name="属性名" value="属性值"/> 定义一个变量,
然后生成get、set方法,
注入集合:
1 <property name="set"> 2 <set> 3 <value>一</value> 4 <value>二</value> 5 <value>三</value> 6 </set> 7 </property> 8 <property name="list"> 9 <list> 10 <value>一list</value> 11 <value>二list</value> 12 <value>三list</value> 13 </list> 14 </property> 15 <property name="map"> 16 <map> 17 <entry key="key1" value="v1"></entry> 18 <entry key="key2" value="v2"></entry> 19 <entry key="key3" value="v3"></entry> 20 </map> 21 </property> 22 <property name="map1"> 23 <map> 24 <entry key="key-map1" value="value-map1"></entry> 25 <entry key="key-map2" value="value-map2"></entry> 26 <entry key="key-map3" value="value-map3"></entry> 27 </map> 28 </property>
通过构造器注入值
1 <constructor-arg index="0" ref="personDao1"></constructor-arg> 2 <constructor-arg index="1" value = "sss"></constructor-arg>
index表示构造器参数的索引,从0开始
使用注解的方式注入依赖对象
@Autowired或者@Resource注解进行装配。但我们需要在xml配置文件中配置一下信息。
@Autowired:默认按类型进行装配
@Resource:默认按名称进行装配,名称找不到再按类型装配
@Resource
private PersonDao personDao1;
根据字段名称,到beans.xml中寻找名称相同的bean,然后将这个bean注入进来
如果找不到就会根据类型去找
不一定要注入在字段上,还可以注入到set方法上
当一个项目需要注入多个bean时,配置文件就会变的臃肿,因此在spring2.5的时候为我们提供
了<context:component-scan base-package="cn.itcast"></context:component-scan>
去自动扫描包下面的标注了注解@Service和@Repository和@component和@Controller
的类,并将这些类自动纳入spring容器中管理。同时可以为这些类指定作用域和名字哦,如:@Resource("name1") @Scope("pototype"),如果没有指定名称的话,这时候ctx.getBean("bean名称")中的bean名称就是类名称,但首字母小写
被@PostConstructs注解的方法是在Bean初始化时被调用的方法
被@PreDestory注解的方法是Bean实例被销毁之前调用该方法
AOP--切面
proxy代理类,只有是面向接口编程时 才能使用proxy代理类
目标对象必须要实现接口
代理对象实现了目标对象的所有方法,
使用cglib创建代理对象
springAOP
定义一个切面(基于注解):
1 /** 2 * 切面 3 * 4 */ 5 @Aspect 6 public class MyInterceptor { 7 @Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))") 8 private void anyMethod() {}//声明一个切入点 9 10 @Before("anyMethod() && args(name)") 11 public void doAccessCheck(String name) { 12 System.out.println("前置通知:"+ name); 13 } 14 @AfterReturning(pointcut="anyMethod()",returning="result") 15 public void doAfterReturning(String result) { 16 System.out.println("后置通知:"+ result); 17 } 18 @After("anyMethod()") 19 public void doAfter() { 20 System.out.println("最终通知"); 21 } 22 @AfterThrowing(pointcut="anyMethod()",throwing="e") 23 public void doAfterThrowing(Exception e) { 24 System.out.println("例外通知:"+ e); 25 } 26 27 @Around("anyMethod()") 28 public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { 29 //if(){//判断用户是否在权限 30 System.out.println("进入方法"); 31 Object result = pjp.proceed(); 32 System.out.println("退出方法"); 33 //} 34 return result; 35 } 36 37 }
定义一个切面(基于配置文件):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 9 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> 10 <aop:aspectj-autoproxy/> 11 <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean> 12 <bean id="aspetbean" class="cn.itcast.service.MyInterceptor"/> 13 <aop:config> 14 <aop:aspect id="asp" ref="aspetbean"> 15 <aop:pointcut id="mycut" expression="execution(* cn.itcast.service..*.*(..))"/> 16 <aop:before pointcut-ref="mycut" method="doAccessCheck"/> 17 <aop:after-returning pointcut-ref="mycut" method="doAfterReturning"/> 18 <aop:after-throwing pointcut-ref="mycut" method="doAfterThrowing"/> 19 <aop:after pointcut-ref="mycut" method="doAfter"/> 20 <aop:around pointcut-ref="mycut" method="doBasicProfiling"/> 21 </aop:aspect> 22 </aop:config> 23 </beans>
spring aop execution表达式说明
1 在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 2 3 例如定义切入点表达式 execution(* com.sample.service.impl..*.*(..)) 4 5 execution()是最常用的切点函数,其语法如下所示: 6 7 整个表达式可以分为五个部分: 8 9 1、execution(): 表达式主体。 10 11 2、第一个*号:表示返回类型,*号表示所有的类型。 12 13 3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。 14 15 4、第二个*号:表示类名,*号表示所有的类。 16 17 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。