一、Spring的Bean注解扫描
1,在Spring配置文件添加注解扫描
<!--开启注解扫描 -->
<context:component-scan
base-package="com.itcast"/>
2,在相关类上面添加注解
@Component(value="userDao")
public class UserDaoImpl implements UserDao {
@Override
public void sayHello() {
System.out.println("Hello Spring Annotation...");
}
}
3,添加测试类
@Test
public void demo2() {
ApplicationContext apc =
new ClassPathXmlApplicationContext("applicationContext.xml";
UserDao userDao = (UserDao) apc.getBean("userDao");
userDao.sayHello();
}
二、Spring的bean管理常用的注解
1,类注解
@component的三个衍生注解
- @controller :WEB层
- @service :业务层
- @Repository:持久层
2,属性注解
@value:用于注入普通类型
@AutoWared:自动装配(默认按类型进行装配)
@Qualifier:强制使用名称注入
@Resource:相当于@Qualifier和@AutoWared一起使用
3,Bean的作用范围
@Scope(value="prototype") 配置多利 @Scope(value="singleton") 配置单利
public class UserServiceImp{
//作用在类上
}
4,Bean生命周期
@PostConStruct :相当于init-method
@PreDestory:相当于destory-method
@Component(value = "userService")
public class UserServiceImp implements UserServiceInter {
@Value(value = "张三")
private String name;
@Resource(name = "userdao") // 这是java 的注解
private UserDao userDao;
@Override
public void sysHello() {
System.out.println("hello word" + name);
userDao.save();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@PostConstruct // 生命周期相当于init
public void init() {
System.out.println("init....");
}
@PreDestroy // 生命周期相当于destory
public void destory() {
System.out.println("destory");
}
}
三、Spring 的Bean的管理方式的对比
实际开发中Bean由xml注解,属性使用注解注入。
四、Spring基于AOP的开发
1,相关jar包
* spring的传统AOP的开发的包
spring-aop-4.2.4.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
* aspectJ的开发包:
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar
2,通知类型
前置通知:在目标方法执行之前执行
后置通知:在目标方法执行之后执行
环绕通知:在目标方法执行前和执行后执行
异常抛出通知:在目标方法出现异常的时候执行
最终通知:无论目标方法是否出现异常 最终通知都会执行
3,切入点表达式
execution(表达式)
表达式:[方法方位修饰符] 方法返回值 包名.类名.方法名(方法的参数)
execution(public void com.itcast.aop.test1.CustomImp.save())
4,前置通知案例
(1)定义切面类
/**
* 切面类:切入点+通知
*/
public class MyAspectXml {
/**
* 通知
*/
public void log() {
System.out.println("记录通知。。。。。");
}
}
(2)定义通知类
@Repository(value = "custom2")
public class CustomImp implements CustomInter {
@Override
public void save() {
// int a=10/0;模拟异常
System.out.println("save.........");
}
@Override
public void update() {
System.out.println("update.........");
}
}
3,配置xml
<!--开启注解扫描 -->
<context:component-scan base-package="com.itcast"></context:component-scan>
<bean id="custome" class="com.itcast.aop.test1.CustomImp"></bean>
<!--配置切面类 -->
<bean id="myAspectxml" class="com.itcast.aop.test1.MyAspectXml"></bean>
<!-- 配置Aop -->
<aop:config>
<!--配置切面类:切入点 +通知 (类型) -->
<!--
切面类表达式:
1,execution 必须写,固定数值
2, public 可以省略不写
3,void 返回值 可以用*代表所有返回类型,返回值类型不能不写
4,包路径可以使用*代替
5,*Imp 代表类的
6,*ve 代表方法以ve结尾的
7,方法参数 ..代表任意参数,*只代表一个参数
-->
<aop:aspect ref="myAspectxml">
<!-- 配置前置通知,在save方法执行之前执行 -->
<!-- 切入点的表达式 excution(public void com.itcast.aop.test1.CustomImp.save() )-->
<aop:before method="log"
pointcut="execution (public void com.itcast.aop.test1.CustomImp.save())"/>
</aop:aspect>
</aop:config>
4, 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test {
@Autowired
@Qualifier(value="custome")
private CustomInter customInter;
@Test
public void run(){
customInter.save();
}
}
5,其他通知
<aop:aspect ref="myAspectxml">
<!-- 前置通知,在save方法执行之前执行 -->
<aop:before method="log" pointcut="execution (public void com.itcast.aop.test1.CustomImp.save())"/>
<!-- 最终通知,在save方法之后执行 -->
<aop:after method="log"
pointcut="execution (public * com.itcast.aop.*.*Imp.*ve(..))"/>
<!-- 后置通知 -->
<aop:after-returning method="runAfter" pointcut="execution (public void com.itcast.aop.*.CustomImp.save())"/>
<!--环绕通知-->
<aop:around method="around" pointcut="execution (public void com.itcast.aop.*.CustomImp.save())"/>
</aop:aspect>
注意:
1,后置通知,如有程序出现异常,不会执行通知
2,最终通知,方法执行成功或者抛出异常都会执行
3,
/**
* 环绕通知:方法执行之前和方法执行之后,默认情况下目标对象的方法不能执行的,
* 需要手动让目标对象执行。
*/
public void around(ProceedingJoinPoint joinPoint) {
System.out.println("环绕通知前。。。。。");
//手动让目标对象进行执行
try {
joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕通知后。。。。。");
}
五、源码