Spring编程<四>
自动代理技术:
配置文件中的自动代理:
在配置文件中加:
使得每次使用bean时,他会自动给bean添加切面advisor;
<!-- 自动代理,自动找 Advisor-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
也可以写我们自己的自动代理
/*
* 自定义自动代理:
* 2个知识点:
* 1)获取项目中的全局容器:通过实现一个监听器 ApplicationContextAware监听器接口
* ----该技术可以让一个普通类(非Web环境)获取到项目的全局bean容器
* 2)获取当前其他模块从bean容器中取出的bean,通过实现BeanPostProcessor监听器接口(拿到后,我来处理)
*/
public class MyAutoProxyCreator implements ApplicationContextAware,BeanPostProcessor{
private ApplicationContext ctx=null;
@Override
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
this.ctx=ctx;
}
下面2个函数是后处理Bean的///
@Override//参数1为当前从容器中读出 bean
public Object postProcessAfterInitialization(Object bean, String str)
throws BeansException {
if (bean instanceof Person) {
//用户 当前将要获取的bean 转换成代理后的对象(bean),然后返回
ProxyFactoryBean factory = new ProxyFactoryBean();
factory.setTarget(bean);//原型
//到bean容器(ctx)中,遍历出所有advisor,添加到factory中,本来要获取Map,本例简化只拿一个
Advisor ad = ctx.getBean(Advisor.class);//会到bean中找该接口实现类创建的
factory.addAdvisors(ad);
return factory.getObject();
}else{
return bean;
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String str)
throws BeansException {
return bean;
}
}
关于切点语言:
演示需要的Person类
/*
*切点语言:
* 1)框架 execution(切点语言表达式)
* 2)表达式格式: 返回类型 包名[子包名...].类名.方法名(参数类型列表)
* 3)"." 在包名与报名 或 包名与类名之间 或 类名与方法名 之间的间隔符
* 4)".." 在包路径位置代表的是 任意深 的目录,如果在参数类型列表中 代表的是 任意个数与类型的参数
* 5)"*" 是操作系统中的通配符 代表任意字符
*/
演示:
//演示切点语言
@Test
public void t1(){
//代理工厂
ProxyFactoryBean factory = new ProxyFactoryBean();
//声明切点
AspectJExpressionPointcut cut =new AspectJExpressionPointcut();
//设置切点表达式--切点语言
//cut.setExpression("execution( void cn.hncu.v2.Person.*() )");拦Person中所有空参方法
//cut.setExpression("execution( void cn.hncu.v2.Person.*(String) )");拦所有返回类型为空,参数类型为String
//cut.setExpression("execution( void cn.hncu.v2.Person.*(*) )");//拦返回空,一个参数
//cut.setExpression("execution( * cn.hncu.v2.Person.*(*) )");//拦返回类型任意,一个参数
//cut.setExpression("execution( String cn.hncu.v2.Person.*(..) )");//拦返回类型String,任意参数
//返回类型为任意,cn.hncu下的任意子包,任意深度,son结尾,任意函数名,任意参数
cut.setExpression("execution( * cn.hncu..*son.*(..) )");
//至少一个参数
// cut.setExpression("execution( * cn.hncu..*son.*(*,..) )");
//通知
Advice advice= new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("...前...");
Object res=invocation.proceed();
System.out.println("...后...");
return res;
}
};
//切面= 切点 + 通知
Advisor advisor=new DefaultPointcutAdvisor(cut, advice);
//把切面加到代理工厂
factory.addAdvisor(advisor);
//从工厂取出的bean都是被代理过的
Person p = new Person();
factory.setTarget(p);
p=(Person) factory.getObject();
p.run();
p.hello();
p.fun("abc");
p.abc("abc123");
p.ok("ok", 8);
}