Spring AOP:
首先看一个Spring装入bean的简单例子:
public class Customer {
pirvate String name;
private String age;
...set or get method
...toString method
}
public class CustomerDao {
public Customer getCustomer() {
return new Customer();
}
}
public class CustomerService {
CustomerDao customerDao;
public setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
public Customer getCustomer() {
customerDao.getCustomer();
}
}
对应的applicationContext.xml配置文件:
(1)完整的xml配置文件模式(set方法注入bean)
<bean id="customerDao" class="../../CustomerDao" />
<bean id="customerService" class="../../CustomerService">
<property name="customerDao" ref="customerDao" />
</bean>
(2)使用自动扫描组件的模式
<context:annotation-config /> //自动载入所有注解所需要的bean
<context:component-scan base-package="com.andy"></context:component-scan> //扫描所有组件,并且给这些组件自动注入bean
组件:@component包括有@controller @service @Repository
所有的bean装入完毕后,需要在注入的地方使用自动注入的注解:@Autowired
(3)使用构造器注入
<constructor-arg ref="...">
</constructor-arg>
补充:
并不是所有的bean的属性值都要写入到配置文件中,可以将属性值写入.properties文件中,
配置文件载入.properties文件:<context:property-placeholder location="classpath:/application.properties" />
在配置文件中,使用${key}的方式获取在.properties文件中对应的value的值
以上是spring注入的几种方式,那么接下来开始探讨spring aop
类似上面的CustomerService类中的getCustomer方法,我们现在需要在这个方法执行之前,或者之后,做一些事情,该如何实现,这就是spring aop能够解决的问题。
spring aop中包括四种类型通知(advices)的支持:
(1)方法执行前 ==> MethodBeforeAdvice
(2)方法执行后 ==> AfterReturningAdvice
(3)方法抛出异常后 ==> ThrowsAdvice
(4)环绕通知 ==> MethodInterceptor
public invoke(MethodInvocation methodInvocation) throws Throwable {
try {
// do something before method action
Object result = methodInvocation.proceed();
// do something after method action
} catch(Excepiton e) {
// do something when catch exception
}
}
配置文件实现代理类:
<bean id="...Advice" class="../../..Advice" />
<bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="customerService" />
<property name="interceptorNames">
<list>
<value>..Advice</value>
</list>
</property>
</bean>
以上是spring aop面向切面的一些操作,它对代理对象的所有方法实现了拦截操作,实际开发中,我们往往需要对某一指定名称的方法进行拦截。
那么接下来就需要去了解spring aop中的切点是什么:
切点就是被代理类中的某个点,或者说是某个方法。
通过切点拦截,有两种匹配切点的方法:
(1)名称匹配 NameMatchMethodPointcut
<bean id="customerPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName" value="getCustomer" />
</bean>
<bean id="customerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="customerPointcut" />
<property name="advice" ref="../../..Advice" />
</bean>
以上需要分别写出pointcut和advisor的bean,可以将这两者结合:
<bean id="customerAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="mappedName" value="getCustomer" />
<property name="advice" value="../../..Advice" />
</bean>
proxy: {
target: "被代理的类"
interceptorNames: {
是一个list,里面可以直接放多个advice,或者
多个advisor: {
pointcut: 匹配的切点(方法)
advice: advice
}
}
}
(2)正则匹配 RegexpMethodYiibaicutAdvisor
<bean id="customerAdvisor" class="org.springframework.sop.support.RegexpMethodPointcutAdvisor">
<property name="patterns">
<list>
<value>.*URL.*</value>
<value>.*DAO.*</value>==>拦截DAO层中所有含有DAO的方法,来支持事务
</list>
</property>
<property name="advice" ref="../../..Advice" />
</bean>
以上是对某一个bean实现代理,拦截该bean中某个特定pointcut或所有方法的讲解。
那么如果需要对所有的dao层中所有的bean都进行代理,实现事务处理,那么岂不是需要写很多代理类呢?
spring aop提供了自动创建代理的方法:
<bean id="customerAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="mappedName" value="getCustomer" />
<property name="advice" ref="../..Advice" />
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>customerAdvisor</value>
</list>
</property>
</bean>
还有一个威力巨大的自动创建代理的方法:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
这种方法,会为所有的bean,只要包含advisor中pointcut方法名(getCustomer方法名)的,全部自动穿件代理,来支持AOP
首先看一个Spring装入bean的简单例子:
public class Customer {
pirvate String name;
private String age;
...set or get method
...toString method
}
public class CustomerDao {
public Customer getCustomer() {
return new Customer();
}
}
public class CustomerService {
CustomerDao customerDao;
public setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
public Customer getCustomer() {
customerDao.getCustomer();
}
}
对应的applicationContext.xml配置文件:
(1)完整的xml配置文件模式(set方法注入bean)
<bean id="customerDao" class="../../CustomerDao" />
<bean id="customerService" class="../../CustomerService">
<property name="customerDao" ref="customerDao" />
</bean>
(2)使用自动扫描组件的模式
<context:annotation-config /> //自动载入所有注解所需要的bean
<context:component-scan base-package="com.andy"></context:component-scan> //扫描所有组件,并且给这些组件自动注入bean
组件:@component包括有@controller @service @Repository
所有的bean装入完毕后,需要在注入的地方使用自动注入的注解:@Autowired
(3)使用构造器注入
<constructor-arg ref="...">
</constructor-arg>
补充:
并不是所有的bean的属性值都要写入到配置文件中,可以将属性值写入.properties文件中,
配置文件载入.properties文件:<context:property-placeholder location="classpath:/application.properties" />
在配置文件中,使用${key}的方式获取在.properties文件中对应的value的值
以上是spring注入的几种方式,那么接下来开始探讨spring aop
类似上面的CustomerService类中的getCustomer方法,我们现在需要在这个方法执行之前,或者之后,做一些事情,该如何实现,这就是spring aop能够解决的问题。
spring aop中包括四种类型通知(advices)的支持:
(1)方法执行前 ==> MethodBeforeAdvice
(2)方法执行后 ==> AfterReturningAdvice
(3)方法抛出异常后 ==> ThrowsAdvice
(4)环绕通知 ==> MethodInterceptor
public invoke(MethodInvocation methodInvocation) throws Throwable {
try {
// do something before method action
Object result = methodInvocation.proceed();
// do something after method action
} catch(Excepiton e) {
// do something when catch exception
}
}
配置文件实现代理类:
<bean id="...Advice" class="../../..Advice" />
<bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="customerService" />
<property name="interceptorNames">
<list>
<value>..Advice</value>
</list>
</property>
</bean>
以上是spring aop面向切面的一些操作,它对代理对象的所有方法实现了拦截操作,实际开发中,我们往往需要对某一指定名称的方法进行拦截。
那么接下来就需要去了解spring aop中的切点是什么:
切点就是被代理类中的某个点,或者说是某个方法。
通过切点拦截,有两种匹配切点的方法:
(1)名称匹配 NameMatchMethodPointcut
<bean id="customerPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName" value="getCustomer" />
</bean>
<bean id="customerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="customerPointcut" />
<property name="advice" ref="../../..Advice" />
</bean>
以上需要分别写出pointcut和advisor的bean,可以将这两者结合:
<bean id="customerAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="mappedName" value="getCustomer" />
<property name="advice" value="../../..Advice" />
</bean>
proxy: {
target: "被代理的类"
interceptorNames: {
是一个list,里面可以直接放多个advice,或者
多个advisor: {
pointcut: 匹配的切点(方法)
advice: advice
}
}
}
(2)正则匹配 RegexpMethodYiibaicutAdvisor
<bean id="customerAdvisor" class="org.springframework.sop.support.RegexpMethodPointcutAdvisor">
<property name="patterns">
<list>
<value>.*URL.*</value>
<value>.*DAO.*</value>==>拦截DAO层中所有含有DAO的方法,来支持事务
</list>
</property>
<property name="advice" ref="../../..Advice" />
</bean>
以上是对某一个bean实现代理,拦截该bean中某个特定pointcut或所有方法的讲解。
那么如果需要对所有的dao层中所有的bean都进行代理,实现事务处理,那么岂不是需要写很多代理类呢?
spring aop提供了自动创建代理的方法:
<bean id="customerAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="mappedName" value="getCustomer" />
<property name="advice" ref="../..Advice" />
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>customerAdvisor</value>
</list>
</property>
</bean>
还有一个威力巨大的自动创建代理的方法:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
这种方法,会为所有的bean,只要包含advisor中pointcut方法名(getCustomer方法名)的,全部自动穿件代理,来支持AOP