day39 07-Spring的AOP:自动代理
带有切点的切面或者是不带有切点的切面配置一个类就要配置一段生成代理的代码,这样太麻烦了.
选中orderDao右键watch
JDK动态代理是先创建被代理对象,然后在创建代理对象的时候传入被代理对象.
@Test public void demo2(){ // 被代理对象 UserDao userDao = new UserDaoImpl(); // 创建代理对象的时候传入被代理对象. UserDao proxy = new JDKProxy(userDao).createProxy(); proxy.add(); proxy.update(); }
把目标对象传入ProxyFactoryBean生成代理.
基于后处理bean在生成类的过程中我就给你生成代理了,返回代理对象.所以后处理bean生成的那个类就已经是代理了.
/* * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; /** * Factory hook that allows for custom modification of new bean instances, * e.g. checking for marker interfaces or wrapping them with proxies. * * <p>ApplicationContexts can autodetect BeanPostProcessor beans in their * bean definitions and apply them to any beans subsequently created. * Plain bean factories allow for programmatic registration of post-processors, * applying to all beans created through this factory. * * <p>Typically, post-processors that populate beans via marker interfaces * or the like will implement {@link #postProcessBeforeInitialization}, * while post-processors that wrap beans with proxies will normally * implement {@link #postProcessAfterInitialization}. * * @author Juergen Hoeller * @since 10.10.2003 * @see InstantiationAwareBeanPostProcessor * @see DestructionAwareBeanPostProcessor * @see ConfigurableBeanFactory#addBeanPostProcessor * @see BeanFactoryPostProcessor */ public interface BeanPostProcessor { /** * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code> * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; if * <code>null</code>, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /** * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code> * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding <code>bean instanceof FactoryBean</code> checks. * <p>This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; if * <code>null</code>, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
BeanNameAutoProxyCreator根据Bean名称创建代理;DefaultAdvisorAutoProxyCreator默认切面的增强,默认切面的代理.切面中已经包含要代理类的信息,那就可以直接按照切面的信息来生成代理.
package cn.itcast.spring3.demo5; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import cn.itcast.spring3.demo3.CustomerDao; import cn.itcast.spring3.demo4.OrderDao; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class SpringTest5 { @Autowired @Qualifier("orderDao")//不用注入代理了,直接注入真实对象,因为它增强之后的类就是代理类. private OrderDao orderDao; @Autowired @Qualifier("customerDao") private CustomerDao customerDao; @Test public void demo1(){ orderDao.add(); orderDao.delete(); customerDao.update(); } }
package cn.itcast.spring3.demo6; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import cn.itcast.spring3.demo3.CustomerDao; import cn.itcast.spring3.demo4.OrderDao; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext3.xml") public class SpringTest6 { @Autowired @Qualifier("orderDao")//不用注入代理了,直接注入真实对象,因为它增强之后的类就是代理类. private OrderDao orderDao; @Autowired @Qualifier("customerDao") private CustomerDao customerDao; @Test public void demo1(){ orderDao.add(); orderDao.update(); orderDao.delete(); customerDao.add(); } }
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入beans的头 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 不带有切点的切面 --> <!-- 定义目标对象 --> <bean id="customerDao" class="cn.itcast.spring3.demo3.CustomerDaoImpl"> </bean> <!-- 定义增强 增强对象--> <bean id="beforeAdvice" class="cn.itcast.spring3.demo3.MyBeforeAdvice"> </bean> <!-- 带有切点的切面 --> <!-- 定义目标对象 --> <bean id="orderDao" class="cn.itcast.spring3.demo4.OrderDao"></bean> <!-- 定义增强 --> <bean id="aroundAdvice" class="cn.itcast.spring3.demo4.MyAroundAdvice"></bean> <!-- 自动代理:按名称的代理 后处理bean不需要配置id,基于后处理bean,后处理bean不需要配置id 因为它是由框架进行调用的.--> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames" value="*Dao"></property><!-- 带Dao结尾的都生成增强 --> <property name="interceptorNames" value="beforeAdvice"></property><!-- 使用前置增强 --> </bean> </beans>
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入beans的头 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 不带有切点的切面 --> <!-- 定义目标对象 --> <bean id="customerDao" class="cn.itcast.spring3.demo3.CustomerDaoImpl"> </bean> <!-- 定义增强 增强对象--> <bean id="beforeAdvice" class="cn.itcast.spring3.demo3.MyBeforeAdvice"> </bean> <!-- 带有切点的切面 --> <!-- 定义目标对象 --> <bean id="orderDao" class="cn.itcast.spring3.demo4.OrderDao"></bean> <!-- 定义增强 --> <bean id="aroundAdvice" class="cn.itcast.spring3.demo4.MyAroundAdvice"></bean> <!-- 定义一个带有切点的切面 --> <bean id="mypointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="pattern" value=".*add.*"></property> <property name="advice" ref="aroundAdvice"></property> </bean> <!-- 自动生成代理 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean> </beans>