本篇玩转aop的配置文件和加载bean
测试方法1:
@Test //相比上一版本:把属性值用匿名内部bean的方式封装,结构性好一些
public void t2(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/aop/v2/t2.xml");
Person p = ctx.getBean("factory",Person.class);
//p.run();
p.abc();
}
配置文件:
<!-- 切面=切点+通知 -->
<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut">
<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*run.*"></property>
</bean>
</property>
<!-- 匿名内部bean的属性封装方式 -->
<property name="advice">
<bean class="cn.hncu.aop.v1.AroundAdviceImpl"></bean>
</property>
</bean>
<bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="cn.hncu.aop.Person"></bean>
</property>
<property name="interceptorNames">
<list>
<value>advisor</value>
</list>
</property>
</bean>
测试方法2:
@Test //相比上一版本:把切面bean从DefaultPointcutAdvisor类改成用RegexpMethodPointcutAdvisor类实现
public void t3(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/aop/v2/t3.xml");
Person p = ctx.getBean("factory",Person.class);
p.run();
p.abc();
}
配置文件:
<!-- 切面=切点+通知 -->
<bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--相比上一版本,改变的地方 -->
<property name="patterns">
<list>
<value>.*run.*</value>
<value>.*abc.*</value>
</list>
</property>
<!-- 匿名内部bean的属性封装方式 -->
<property name="advice">
<bean class="cn.hncu.aop.v1.AroundAdviceImpl"></bean>
</property>
</bean>
<bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="cn.hncu.aop.Person"></bean>
</property>
<property name="interceptorNames">
<list>
<value>advisor</value>
</list>
</property>
</bean>
测试方法3:
@Test //相比上一版本:采用自动代理bean技术
public void t4(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/aop/v2/t4.xml");
//Person p = ctx.getBean(Person.class); //如果xml中只有一个这种类型的bean
Person p = ctx.getBean("p",Person.class); //如果xml中不止一个这种类型的bean,要加上id以指定哪一个
p.run();
p.abc();
User u = ctx.getBean(User.class);
u.run();
}
配置文件将factory修改为一句:
<!-- 自动代理bean -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
测试方法4:
@Test //相比上一版本:采用我们自己开发的自动代理bean技术
public void t5(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/aop/v2/t5.xml");
Person p = ctx.getBean("p",Person.class);
p.run();
p.abc();
User u = ctx.getBean(User.class);
u.run();
}
配置文件采用自己写的代理bean
实现BeanPostProcessor接口可以让我们在bean创建完,于未初始化的前后进行监听处理
实现ApplicationContextAware接口,可以让我们写的类中能够拿到当前项目的ctx容器
package cn.hncu.aop.v2;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import cn.hncu.aop.Person;
//实现BeanPostProcessor接口可以让我们在bean创建完,于未初始化的前后进行监听处理
//实现ApplicationContextAware接口,可以让我们写的类中能够拿到当前项目的ctx容器
public class MyAutoProxy implements BeanPostProcessor,ApplicationContextAware {
private ApplicationContext ctx;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean; //直接放行
}
@Override //把bean增强成"代理后的bean"返回
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
//如果bean是Person类型则拦截,否则直接放行
if (bean instanceof Person) {
ProxyFactoryBean factory = new ProxyFactoryBean();
factory.setTarget(bean);//原型对象
Advisor advice = ctx.getBean(Advisor.class);
factory.addAdvisors(advice);//切面
return factory.getObject();
}
return bean;
}
@Override
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
this.ctx = ctx;
}
}