Spring框架官网学习内容(不太好找)
小知识点:
一、required
1、@Autowired(required = false)
说明对象可以为null,否则不可以为空。默认required=true。
理解:当required=false时,该属性在spring中可以为没有注册的状态,且打印该属性为null。
如果required=true时,该属性在spring中不可以为没有注册的状态,运行时报错。
具体测试代码:
测试方案,Cat类,TestDao类中包含Car类,Test类执行
1、required=true的情况
Cat类
package com.qian.pojo;
public class Cat {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
TestDao类
package com.qian.dao;
import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;
public class testDao {
@Autowired //默认即为required=true
private Cat cat;
public Cat getCat() {
return cat;
}
}
测试类
package com.qian.service;
import com.qian.dao.testDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ServiceTest {
public static void main(String[] args){
//获取ApplicationContext,拿到Spring的容器,通过配置文件获取
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//容器在手,天下我有,需要什么,就直接get什么
testDao testDao = context.getBean("testDao", testDao.class);
System.out.println(testDao.getCat());
}
}
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean name="testDao" class="com.qian.dao.testDao" >
</bean>
</beans>
测试结果报错
2、required=false的情况
TestDao变化外,其余不变
package com.qian.dao;
import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;
public class testDao {
@Autowired(required = false)
private Cat cat;
public Cat getCat() {
return cat;
}
}
演示结果:
二、qualifier 配合autowired使用
autowired是通过类型来进行类的装配
<bean name="testDao" class="com.qian.dao.testDao" >
</bean>
其中name为名,class为类型
因此,当同一个class中有两个bean在spring容器中被注册时,会报错(奇怪的当其中第一个bean的name为类名的小写时,此情况并不会报错)
XML文件如下
<bean name="dog2" class="com.qian.pojo.Cat" >
<property name="name" value="001"></property>
</bean>
<bean name="dog" class="com.qian.pojo.Cat" >
<property name="name" value="002"></property>
</bean>
<bean name="testDao" class="com.qian.dao.testDao" >
</bean>
报错如下:
解决方案:加qualifier
package com.qian.dao;
import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class testDao {
@Autowired
@Qualifier(value = "dog") //解决方案在此
private Cat cat;
public Cat getCat() {
return cat;
}
}
三、Resource
Resource先找name,再找类型。功能上等于autowired和qualifier
四、Value 注入元素
联合@component联用
package com.qian.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Cat {
@Value("张三") //此处name将等于"张三"
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
五、@scope(value = "prototype") 用在component下方
package com.qian.dao;
import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "prototype")
public class testDao {
@Autowired
private Cat cat;
public Cat getCat() {
return cat;
}
}
六、Configuration 配置类
注释为重点内容,配置类配置的是spring!!!
package com.qian.config;
import com.qian.dao.TestDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component
//@Configuration代表这是一个配置类,等同于我们之前写的Application.xml
@Configuration
@ComponentScan("com.qian") //可以写扫描,类似之前的扫描包
@import("MyConfiguration.class") //此句没有经过测试
public class MyConfiguration {
//注册一个bean,就相当于我们之前写的一个bean标签
//这个方法的名字,就相当于bean标签中的id属性
//这个方法的返回值,就相当于bean标签的calss属性
@Bean
public TestDao getTestDao(){
return new TestDao();
}
}
获取注解上下文来获取注册的bean,注意方法名是name,返回对象的类
package com.qian.service;
import com.qian.config.MyConfiguration;
import com.qian.dao.TestDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ServiceTest {
public static void main(String[] args){
//如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载!
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
TestDao testDao = context.getBean("getTestDao", TestDao.class);
System.out.println(testDao.getCat());
}
}
七、AOP
1、Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies.
默认使用JDK代理
2、使用AOP的三种方式:
2.1
首先,AOP需要pom中更新weaver包,重要 !!!如果没有调入该包,编译不报错,运行时报错!!
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
第一种:调用API接口,配合spring.xml完成功能。
java类,实现MethodBeforeAdvice,并实现before方法
package com.qian.aop;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class BeforeLog implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable{
System.out.println(o.getClass().getName()+"的"+method.getName()+"方法被执行了");
}
}
Service
package com.qian.service;
public interface UserService {
public void add();
public void remove();
public void select();
public void modify();
}
实现类
package com.qian.service.serviceimpl;
import com.qian.service.UserService;
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("执行增加方法");
}
public void remove() {
System.out.println("执行删除方法");
}
public void select() {
System.out.println("执行查询方法");
}
public void modify() {
System.out.println("执行更改方法");
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- <context:component-scan base-package="com.qian">-->
<!-- </context:component-scan>-->
<!-- <context:annotation-config/>-->
<bean id="userService" class="com.qian.service.serviceimpl.UserServiceImpl"/>
<bean id="beforeLog" class="com.qian.aop.BeforeLog"/>
<!-- <bean id="afterLog" class="com.kaung.log.AfterLog"/>-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.qian.service.UserService.*(..))" />
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<!-- <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
</aop:config>
</beans>
测试类
package com.qian.service;
import com.qian.config.MyConfiguration;
import com.qian.dao.TestDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ServiceTest {
public static void main(String[] args){
//如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载!
// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
// TestDao testDao = context.getBean("getTestDao", TestDao.class);
// System.out.println(testDao.getCat());
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService)context.getBean("userService");
userService.add();
}
}
测试结果
第二种、自定义java类
自定义java类,作为切面方法
package com.qian.aop;
public class Diy {
public void before(){
System.out.println("============方法执行前===========");
}
public void after(){
System.out.println("===========方法执行后============");
}
}
spring.xml 变化较大
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- <context:component-scan base-package="com.qian">-->
<!-- </context:component-scan>-->
<!-- <context:annotation-config/>-->
<bean id="userService" class="com.qian.service.serviceimpl.UserServiceImpl"/>
<bean id="beforeLog" class="com.qian.aop.BeforeLog"/>
<!-- 第一种方式,以接口的方式-->
<!-- <bean id="afterLog" class="com.kaung.log.AfterLog"/>-->
<!-- <aop:config>-->
<!-- <aop:pointcut id="pointcut" expression="execution(* com.qian.service.UserService.*(..))" />-->
<!-- <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>-->
<!--<!– <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>–>-->
<!-- </aop:config>-->
<!-- 第二种方式,以自定义类的方式-->
<!-- 注入自定义类-->
<bean name="diy" class="com.qian.aop.Diy"></bean>
<aop:config>
<!-- 自定义切面,ref要引用的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))"/>
<!--具体运行方法,通知-->
<aop:before method="before" pointcut-ref="point" />
<aop:after method="after" pointcut-ref="point" />
</aop:aspect>
</aop:config>
</beans>
其余类与第一种一样
运行结果
第三种方案 注解AOP
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.qian">
</context:component-scan>
<!-- <context:annotation-config/>-->
<!-- 开启注解支持-->
<aop:aspectj-autoproxy/>
<bean id="userService" class="com.qian.service.serviceimpl.UserServiceImpl"/>
<!-- <bean id="beforeLog" class="com.qian.aop.BeforeLog"/>-->
<!-- 第一种方式,以接口的方式-->
<!-- <bean id="afterLog" class="com.kaung.log.AfterLog"/>-->
<!-- <aop:config>-->
<!-- <aop:pointcut id="pointcut" expression="execution(* com.qian.service.UserService.*(..))" />-->
<!-- <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>-->
<!--<!– <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>–>-->
<!-- </aop:config>-->
<!-- 第二种方式,以自定义类的方式-->
<!-- 注入自定义类-->
<!-- <bean name="diy" class="com.qian.aop.Diy"></bean>-->
<!-- <aop:config>-->
<!--<!– 自定义切面,ref要引用的类–>-->
<!-- <aop:aspect ref="diy">-->
<!-- <!–切入点–>-->
<!-- <aop:pointcut id="point" expression="execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))"/>-->
<!-- <!–具体运行方法,通知–>-->
<!-- <aop:before method="before" pointcut-ref="point" />-->
<!-- <aop:after method="after" pointcut-ref="point" />-->
<!-- </aop:aspect>-->
<!-- </aop:config>-->
</beans>
注解类:
package com.qian.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AnnotationAop {
@Before("execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))")
public void before(){
System.out.println("=========方法运行前=========");
}
@After("execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))")
public void after(){
System.out.println("========方法运行后==========");
}
@Around("execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint pj){
System.out.println("===========环绕前============");
try {
Object proceed = pj.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("============环绕后============");
}
}
运行结果: