(一)初步使用
-
pom.xml
<!--spring依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.5.RELEASE</version> </dependency>
-
创建spring.xml,并注入bean
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 注入bean --> <bean id="TestServiceImpl" class="com.lr.day5.impl.TestServiceImpl"/> </beans>
-
创建测试类,获取读取配置文件,并获取bean
// 读取xml配置文件 ClassPathXmlApplicationContext c = new ClassPathXmlApplicationContext("spring.xml"); // 获取bean //TestService bean = (TestService) c.getBean("TestServiceImpl"); //TestService bean = c.getBean(TestService.class); //如果ioc有多个bean实现了该接口会报错,spring不知道返回给你哪个bean TestService bean = c.getBean("TestServiceImpl", TestService.class); bean.say();
(二)使用set或构造器为bean赋值
-
xml中
<!-- 1.使用set方法为bean赋值 --> <bean id="user1" class="com.lr.day5.bean.User"> <property name="no" value="1"/> <property name="name" value="张三1"/> </bean> <!-- 2.使用构造器为bean赋值 --> <bean id="user2" class="com.lr.day5.bean.User"> <constructor-arg name="no" value="2"/> <constructor-arg name="name" value="张三2"/> </bean> <!-- 3.使用构造器和set方法混合为bean赋值 --> <bean id="user3" class="com.lr.day5.bean.User"> <constructor-arg name="no" value="3"/> <property name="name" value="张三3"/> </bean> <!-- 4.为bean赋值引用,引用ioc的其他bean --> <bean id="superUser1" class="com.lr.day5.bean.SuperUser"> <constructor-arg name="id" value="1"/> <constructor-arg ref="user1"/> </bean> <!-- 5.为bean赋值引用,临时创建bean --> <bean id="superUser2" class="com.lr.day5.bean.SuperUser"> <constructor-arg name="id" value="2"/> <constructor-arg name="user"> <bean class="com.lr.day5.bean.User"> <property name="no" value="04"/> <property name="name" value="李四"/> </bean> </constructor-arg> </bean>
-
获取属性
// 读取xml配置文件 ClassPathXmlApplicationContext c = new ClassPathXmlApplicationContext("spring.xml"); //1.使用set方法为bean赋值 User u1 = c.getBean("user1", User.class); System.out.println(u1); //2.使用构造器为bean赋值 User u2 = c.getBean("user2", User.class); System.out.println(u2); //3.使用构造器和set方法混合为bean赋值 User u3 = c.getBean("user3", User.class); System.out.println(u3); //4.为bean赋值引用,引用为ioc的其他bean SuperUser superUser1 = c.getBean("superUser1", SuperUser.class); System.out.println(superUser1); //5.为bean赋值引用,引用为临时创建的bean SuperUser superUser2 = c.getBean("superUser2", SuperUser.class); System.out.println(superUser2);
-
通过set赋值的方式,需要有无参构造器。
(三)作用域
-
原型模式(prototype):相当于反射新建一个bean返回,多例模式
<bean id="TestServiceImpl" class="com.lr.day5.impl.TestServiceImpl" scope="prototype"/>
-
单例模式(singleton):单例模式,spring默认单例模式
<bean id="TestServiceImpl" class="com.lr.day5.impl.TestServiceImpl" scope="singleton"/>
如果使用了多例/原型模式
// 读取xml配置文件
ClassPathXmlApplicationContext c = new ClassPathXmlApplicationContext("spring.xml");
// 获取bean
TestService bean1 = c.getBean("TestServiceImpl", TestService.class);
TestService bean2 = c.getBean("TestServiceImpl", TestService.class);
sout(bean1 == bean2); // => false
(四)IOC基于注解实现
-
xml中添加名称空间
xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
-
开启扫描
<!-- 开启注解扫描 --> <context:component-scan base-package="com.lr.day5"/>
-
bean上添加注解自动注入IOC容器
@Component(组件上使用)、@Repository(dao层)、@Service(服务层)、@Controller(控制器)都可以
-
字段上添加注解@Autowired获取IOC中的bean
-
查看其他注解和@Component的区别,@Repository、@Service、@Controller注解都是被@Component所标识,所以本质上没多大区别。
-
@Component的value属性:相当于xml的bean设置id
如果没有指定value,默认设置bean的id为类名的驼峰形式
-
@Autowired:注入bean,相当于通过class获取bean –
c.getBean(TestService.class);
,value属性是boolean值,true表示没找到bean抛异常(默认值),false表示没找到返回null。 -
@Scope:相当于xml的bean设置scope,加在类上,配合@Component等注解使用。
-
@Qualifier:翻译为限定词或限定符,相当于通过id获取bean –
c.getBean(TestService.class);
,和@Autowired配合使用。@Autowired @Qualifier("testServiceImpl") TestService testService;
-
@Resource:根据字段名去获取ioc中的bean,获取不到就通过class去获取。如果指定name值,就通过name去获取ioc的bean。(并且这个是java提供的,一般使用@Autowired)
(五)AOP
-
引入maven
<!--spring+aop依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency>
-
配置名称空间
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
-
创建切面类
public class PointCut { public void after(JoinPoint joinPoint) throws Throwable { System.out.println("after~"); } public void before(JoinPoint joinPoint) throws Throwable { System.out.println("before~"); } public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("around~"); return proceedingJoinPoint.proceed(); } public void afterThrowing(JoinPoint joinPoint) throws Throwable { System.out.println("afterThrowing~"); } public void afterReturning(JoinPoint joinPoint) throws Throwable { System.out.println("afterReturning~"); } }
-
配置切面bean
<!-- 注入切面bean --> <bean id="aspect" class="com.lr.day5.aop.PointCut"/>
aspect翻译为切面
-
配置aop,先配置切入点(被增强的方法),再配置切面
<aop:config> <!-- 配置切入点 --> <aop:pointcut id="pointcut" expression="execution(* com.lr.day5.impl.TestServiceImpl.*(..))"/> <!-- 配置切面 --> <aop:aspect ref="aspect"> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> <aop:around method="around" pointcut-ref="pointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
expression表达式:
execution(* com.lr.day5.impl.TestServiceImpl.*(..)) 1 2 3 4 5 1:声明表达式() 2:方法的权限访问符 3:类的全路径 4:方法名 5:参数 上面的表达式表示:com.lr.day5.impl.TestServiceImpl类的所以方法
(六)AOP基于注解实现
-
导入maven
<!-- aop注解依赖 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency>
-
xml启用对@AspectJ注解的支持
<!-- 启用对于@AspectJ注解的支持 --> <aop:aspectj-autoproxy/>
-
创建切面类
@Aspect @Component public class PointCut { //execution表达式 private static final String POINT_CUT = "execution(* com.lr.day5.impl.TestServiceImpl.*(..))"; @After(POINT_CUT) public void after(JoinPoint joinPoint) throws Throwable { System.out.println("after~"); } @Before(POINT_CUT) public void before(JoinPoint joinPoint) throws Throwable { System.out.println("before~"); } @Around(POINT_CUT) public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("around~"); return proceedingJoinPoint.proceed(); } @AfterThrowing(POINT_CUT) public void afterThrowing(JoinPoint joinPoint) throws Throwable { System.out.println("afterThrowing~"); } @AfterReturning(POINT_CUT) public void afterReturning(JoinPoint joinPoint) throws Throwable { System.out.println("afterReturning~"); } }
(七)使用工厂模式和动态代理模式简单模拟IOC和AOP
-
创建被代理接口
public interface TestService { void say(); }
-
创建被代理类
@Service public class TestServiceImpl implements TestService { @Override public void say() { System.out.println("hello"); } }
-
创建代理类
public class MyProxy implements InvocationHandler { private Object obj; public MyProxy(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object o = null; System.out.println("增强代码~~~"); o = method.invoke(obj, args); System.out.println("增强代码~~~"); return o; } }
-
创建Bean工厂模拟IOC
public class BeanFacory { private static Map<String, String> IOC = new HashMap<>(); static { IOC.put("test1", "com.lr.day5.impl.TestServiceImpl"); IOC.put("test2", "com.lr.day5.impl.TestServiceImpl2"); } public static <T> T getBean(String id) throws Exception { String className = IOC.get(id); Class<?> clazz = Class.forName(className); Object o = clazz.getDeclaredConstructor().newInstance(); MyProxy myProxy = new MyProxy(o); Object proxy = Proxy.newProxyInstance(myProxy.getClass().getClassLoader(), clazz.getInterfaces(), myProxy); return (T) proxy; } }
-
测试
@Test void getBean() throws Exception { TestService bean = BeanFacory.getBean("test1"); bean.say(); } //输出 增强代码~~~ hello 增强代码~~~