1.SpingIOC/DI
对Category的name属性注入了"category 1"字符串
2.Sping注入对象
对Product对象,注入一个Category对象
1.Product类包含Category
2.更改全局配置
3.编写测试类
3.Spring 注解方式 IOC/DI
使用注解的方式完成注入对象中的效果
1.在实体类那里@Component("") 声明这个类是bean
因为配置里没有初始化属性,所以在实体类声明属性的时候顺便初始化
2.全局配置
3.测试类
4.Spring AOP:(Aspect Oriented Program)面向切面(周边+核心功能)编程
AOP 即 Aspect Oriented Program 面向切面编程
首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。
所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务
所谓的周边功能,比如性能统计,日志,事务管理等等
周边功能在Spring的面向切面编程AOP思想里,即被定义为切面
在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发
然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP
1.新建一个业务类(也就是核心功能)
package com.service;
/**
* 业务类,定义了一个doSomeService()方法的内容
* @author Administrator
*
*/
public class ProductService {
public void doSomeService(){
System.out.println("doSomeService方法");
}
}
2.新建一个切面(本次例子是日志切面)
package com.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 日志切面LoggerAspect
* 功能:在调用核心功能之前和之后分别打印日志
* @author Administrator
*
*/
public class LoggerAspect {
public Object log(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("开始log:"+joinPoint.getSignature().getName());
//proceed()启动目标方法,执行核心功能
Object object = joinPoint.proceed();
System.out.println("结束log:"+joinPoint.getSignature().getName());
return object;
}
}
3.修改全局配置(重点)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.pojo" />
<!-- <context:annotation-config/> 通过关键字c即可获取Category对象,该对象获取的时候,即被注入了字符串"category
1“到name属性中 -->
<bean name="c" class="com.pojo.Category">
<property name="name" value="这是c的name属性category 1" />
</bean>
<bean name="p" class="com.pojo.Product">
<property name="name" value="这是p的name属性的product1" />
<!--使用ref来注入另一个对象 -->
<property name="category" ref="c" />
</bean>
<!--声明业务对象 -->
<bean name="s" class="com.service.ProductService"></bean>
<!--声明日志切面 -->
<bean id="loggerAspect" class="com.aspect.LoggerAspect" />
<!-- 通过aop:config把业务对象与辅助功能编织在一起 -->
<aop:config>
<!-- 切入点,切入service ,切入点的id叫loggerCutpoint,用来标记切入点.
expression:满足expression里的方法后,就会进行切面操作
execution(* com.service.ProductService.*(..)):返回包名以xx开头的类的任意方法
第一个*表示返回任意类型
com.service.ProductService:表示包名以com.service.ProductService开头的任意方法
第二个*表示任意方法
(..)表示方法的参数是任意类型和任意数量
-->
<!--简单说就是,只要com.service这个包中的ProductService类的任意一个函数被调用,
不管你的返回值是什么,都会触发开关,我就会去执行切面,也就是辅助功能 -->
<aop:pointcut id="loggerCutpoint"
expression="execution(* com.service.ProductService.*(..)) " />
<!--下面是切面,日志就是一个切面(辅助功能),切面也可以说就是一个方法而已
切入点可以理解为一个开光,触发了这个开关,就会执行这个切面
id表示切面的名字
ref:切面这个方法所在的类
method:方法的名字
pointcut-ref="loggerCutpoint" :把这个切面与上面的切点关联起来
一个切点是可以关联多个切面的,一个切面只能关联一个方法
-->
<aop:aspect id="logAspect" ref="loggerAspect">
<!-- aop:around为在调用方法前,调用后执行 -->
<aop:around pointcut-ref="loggerCutpoint" method="log" />
</aop:aspect>
<!-- 总结:配置一个切入点,然后再配置一个切面,然后把面放进去,
相当于找到跳远的起点后,起点就是切入点,后面跳多少就是切面 -->
</aop:config>
</beans>
4.测试类
5.运行结果
AOP的相关知识:
1.注解配置
在xml加入下面内容
添加如下3行
<context:component-scan base-package="com.how2java.aspect"/>
<context:component-scan base-package="com.how2java.service"/>
扫描包com.how2java.aspect和com.how2java.service,定位业务类和切面类
<aop:aspectj-autoproxy/>
找到被注解了的切面类,进行切面配置
网站的功能分为核心功能和辅助功能,辅助功能叫做切面
AOP的过程分为两步:1,在业务类中插入切入点,2,将切入点和切面类关联起来
业务类就是核心类,就是网站的主要功能,切面就是辅助功能,日志,统计之类的
通过配置,可以实现,在某个方法调用的时候,触发别的方法执行,就好像在监视目标方法,你被执行,就触发我执行。
AOP术语
1,通知:
通知定义了切面要完成的工作内容和何时完成工作,就是什么时候去做辅助功能,功能具体是什么代码
五种类型
Before——在方法调用之前调用通知
After——在方法完成之后调用通知,无论方法执行成功与否
After-returning——在方法执行成功之后调用通知
After-throwing——在方法抛出异常后进行通知
Around——通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
前四个好理解的,最后一个
around 表示切面在被监视的函数运行前后都会执行,
下面是切面要执行的函数 log,log函数有一个形参 joinPoint 这个可以理解为断点,中间一句代表的就是被监视的程序运行,在被监视的程序运行时,可以替换他的形参,这个是 around 厉害的地方,如果被监视的程序,运行的时候输入的是一个haha字符串作为实参,但是经过log方法之后,这个参数就被替换为abc了
public Object log(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("我在被监视程序之前。。。"); Object object = joinPoint.proceed(new Object[]{"abc"}); System.out.println("我在被监视程序之后。。。" ); return object; }
2,连接点:
在执行正常的功能时,能够插入切面的点。可以作为切入点的点。备选点。
连接点可以是调用方法时、抛出异常时、甚至修改字段时,在这些点,就可以去执行切面。
3,切面:
定义:切面是通知和切点的集合,通知和切点共同定义了切面的全部功能——它是什么,在何时何处完成其功能。
声明切面:
在Spring中,切面就是一个包含通知和切点的对象,是一个Bean,Bean的字段和方法就是该切面的状态和行为,还要通过配置,来指定切入点和通知实现
在xml中,切面使用<aop:aspect>标签指定,ref属性用来引用切面支持Bean。这个bean里面就是用来执行要做的辅助功能的。
4,切点:
定义:如果通知定义了“什么”和“何时”。那么切点就定义了“何处”。切点会匹配通知所要织入的一个或者多个连接点。通常使用明确的类或者方法来指定这些切点。
作用:定义通知被应用的位置(在哪些连接点)
切入点的声明:
切入点在Spring也是一个Bean。
切点的声明有三种定义方式:
1)在<aop:config>标签下使用<aop:pointcut>声明一个切入点Bean,该切入点可以被多个切面使用,对于需要共享使用的切入点最好使用该方式,该切入点使用id属性指定Bean名字,在通知定义时使用pointcut-ref属性通过该id引用切入点,expression属性指定切入点表达式
<aop:config> <aop:pointcut id="pointcut" expression="execution(* cn.javass..*.*(..))"/> <aop:aspect ref="aspectSupportBean"> <aop:before pointcut-ref="pointcut" method="before"/> </aop:aspect> </aop:config>2)在<aop:aspect>标签下使用<aop:pointcut>声明一个切入点Bean,该切入点可以被多个切面使用,但一般该切入点只被该切面使用,当然也可以被其他切面使用,但最好不要那样使用,该切入点使用id属性指定Bean名字,在通知定义时使用pointcut-ref属性通过该id引用切入点,expression属性指定切入点表达式:
<aop:config> <aop:aspect ref="aspectSupportBean"> <aop:pointcut id=" pointcut" expression="execution(* cn.javass..*.*(..))"/> <aop:before pointcut-ref="pointcut" method="before"/> </aop:aspect> </aop:config>3)匿名切入点Bean,可以在声明通知时通过pointcut属性指定切入点表达式,该切入点是匿名切入点,只被该通知使用:
<aop:config> <aop:aspect ref="aspectSupportBean"> <aop:after pointcut="execution(* cn.javass..*.*(..))" method="afterFinallyAdvice"/> </aop:aspect> </aop:config>
5,引入:
引入允许我们向现有的类中添加方法或属性
6,织入:
织入是将切面应用到目标对象来创建的代理对象过程。
切面在指定的连接点被织入到目标对象中,在目标对象的生命周期中有多个点可以织入
- 编译期——切面在目标类编译时期被织入,这种方式需要特殊编译器。AspectJ的织入编译器就是以这种方式织入切面。
- 类加载期——切面在类加载到
- JVM ,这种方式需要特殊的类加载器,他可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5 的 LTW 就支持这种织入方式
- 运行期——切面在应用运行期间的某个时刻被织入。一般情况下,在织入切面时候,AOP 容器会为目标对象动态的创建代理对象。Spring AOP 就是以这种方式织入切面。