1.使用注解配置spring
1.1 引入新的命名空間(約束)
如果是使用eclipse的同學,那么肯定是很熟悉這個了蜓洪。使用idea的話,就不需要自己引入了,idea已經(jīng)將約束添加好了
1.2 在spring的配置文件中開啟注解
<!--指定掃面 bean 包下的所有類 的注解-->
<context:component-scan base-package="bean"/>
1.3 在類中使用注解
// 相當于在xml配置文件中寫<bean name="user" class="bean.user" />
@Component("user") // 早期使用文狱,當初只有component,后續(xù)細化出了下面三個缘挽,用于不同的層瞄崇,方便閱讀
@Service("user") // service層
@Controller("user") // web層
@Repository("user") // dao層
1.4 測試
@Test
public void testFunc01() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user);
}
2. 使用注解
2.1 使用Scpoe
@Repository("user") // dao層
@Scope("prototype")
public class User {
private String name;
private Integer age;
private Dog dog;
2.2 基本數(shù)據(jù)類型賦值
- 在屬性上賦值
通過反射的field賦值,破壞封裝性壕曼,但是可讀性好
public class User {
@Value("tom")
private String name;
@Value("18")
private Integer age;
- 在set方法上賦值
在set方法賦值苏研,推薦使用,但是可讀性不太好
@Value("tom")
public void setName(String name) {
this.name = name;
}
@Value("18")
public Integer getAge() {
return age;
}
2.3 引用類型賦值
先給dog類賦值
@Component("dog")
public class Dog {
@Value("柯基")
private String name;
@Value("3")
private Integer age;
- 手動注入腮郊,指定注入哪個名稱的對象
@Resource(name = "dog")
private Dog dog;
- @Autowired 自動裝配
問題:如果發(fā)現(xiàn)多個類型一致的對象摹蘑,將無法選擇具體注入哪一個對象
如果需要指定注入某一個對象,需要添加輔助注解
在User 中只需要添加注解
@Autowired
@Qualifier("dog2")
private Dog dog;
2.4 創(chuàng)建和銷毀注解
@PostConstruct // 在對象創(chuàng)建后調(diào)用轧飞,相當于init-method
public void init() {
System.out.println("初始化方法調(diào)用");
}
@PreDestroy // 在對象銷毀之前調(diào)用衅鹿,相當于destroy-method
public void destroy() {
System.out.println("銷毀方法調(diào)用");
}
3. spring junit整合測試
這樣就不需要在每個測試方法中都重復(fù)書寫獲取對象的代碼
// 幫我們創(chuàng)建容器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定創(chuàng)建容器使用哪一個配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class Test02 {
@Resource(name = "user")
private User user;
@Test
public void testFunc01() {
System.out.println(user);
}
}
4. spring aop
4.1 aop 名詞
Joinpoint(連接點):目標對象中,所有可以增強的方法过咬。(可以增強的方法)
Pointcut(切入點):目標對象中大渤,已經(jīng)被增強的方法。(已經(jīng)增強的方法)
Advice(通知/增強):增強的代碼掸绞。(例如:打開事務(wù)泵三,關(guān)閉事務(wù))
Target(目標對象):被代理對象
Weaving(織入):將通知應(yīng)用到連接點的過程
6.Proxy(代理):將通知織入到目標對象之后,形成代理對象
7.Aspect(切面):切入點+通知
4.2 配置將通知織入目標對象
- 準備一個通知類
/// 通知類
public class MyAdvice {
public MyAdvice() {
}
// 前置通知 -》目標方法調(diào)用之前調(diào)用
public void before() { System.out.println("這是前置通知"); }
// 后置通知(如果出現(xiàn)異常不會調(diào)用)-》在目標方法調(diào)用之后調(diào)用
public void afterReturning() { System.out.println("這是后置通知"); }
// 環(huán)繞通知 -》在目標方法調(diào)用之前和之后都調(diào)用
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// 調(diào)用目標方法
System.out.println("這是環(huán)繞通知前部分");
Object proceed = pjp.proceed();
System.out.println("這是環(huán)繞通知后部分");
return proceed;
}
// 異常攔截通知 -》如果出現(xiàn)異常會調(diào)用
public void afterException() {
System.out.println("這是異常攔截通知");
}
// 后置通知(如果出現(xiàn)異常仍會調(diào)用)-》在目標方法調(diào)用之后調(diào)用
public void after() {
System.out.println("這是后置通知-出現(xiàn)異常仍會調(diào)用");
}
}
- 配置通知對象和通知方法
<!--配置目標對象-->
<bean name="userService" class="service.UserServiceImpl"></bean>
<!--配置通知對象-->
<bean name="myAdvice" class="springAop.MyAdvice"></bean>
<!--配置將通知織入目標對象-->
<!--
public void service.UserServiceImpl.save()
void service.UserServiceImpl.save()
* service.UserServiceImpl.*()
* service.*ServiceImpl.*(..)
-->
<aop:config>
<aop:pointcut expression="execution(* service.*ServiceImpl.*(..))" id="pc"/>
<aop:aspect ref="myAdvice" >
<!-- 指定名為before方法作為前置通知 -->
<aop:before method="before" pointcut-ref="pc" />
<!-- 后置 -->
<aop:after-returning method="afterReturning" pointcut-ref="pc" />
<!-- 環(huán)繞通知 -->
<aop:around method="around" pointcut-ref="pc" />
<!-- 異常攔截通知 -->
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<!-- 后置 -->
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
3.進行測試
// 幫我們創(chuàng)建容器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定創(chuàng)建容器使用哪一個配置文件
@ContextConfiguration("classpath:springAop/applicationContext.xml")
public class Test03 {
@Resource(name = "userService")
private UserService us;
@Test
public void testFunc01() {
us.save();
}
}
-
結(jié)果輸出
4.3 使用注解配置 將通知織入目標對象
1.在配置文件中開啟自動代理
<aop:aspectj-autoproxy/>
2.在通知類中進行配置
/// 通知類
@Aspect
public class MyAdvice {
@Pointcut("execution(* service.UserServiceImpl.*(..))")
public void pc() {}
// 前置通知 -》目標方法調(diào)用之前調(diào)用
@Before("MyAdvice.pc()")
public void before() { System.out.println("這是前置通知"); }
// 后置通知(如果出現(xiàn)異常不會調(diào)用)-》在目標方法調(diào)用之后調(diào)用
@AfterReturning("MyAdvice.pc()")
public void afterReturning() { System.out.println("這是后置通知 (如果出現(xiàn)異常不會調(diào)用)"); }
// 環(huán)繞通知 -》在目標方法調(diào)用之前和之后都調(diào)用
@Around("MyAdvice.pc()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// 調(diào)用目標方法
System.out.println("這是環(huán)繞通知前部分");
Object proceed = pjp.proceed();
System.out.println("這是環(huán)繞通知后部分");
return proceed;
}
// 異常攔截通知 -》如果出現(xiàn)異常會調(diào)用
@AfterThrowing("MyAdvice.pc()")
public void afterException() {
System.out.println("這是異常攔截通知");
}
// 后置通知(如果出現(xiàn)異常仍會調(diào)用)-》在目標方法調(diào)用之后調(diào)用
@After("MyAdvice.pc()")
public void after() {
System.out.println("這是后置通知(如果出現(xiàn)異常仍會調(diào)用)");
}
}