spring学习02
使用注解实现自动的自动装配
- 添加注解所需要的配置【重要】
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/> //这句话千万不能忘
</beans>
- 在属性上添加 Spring 提供的
@autoWired
注解
//类似下面这样
public class Person {
@Autowired
private Dog dog;
@Autowired
private Cat cat;
private String name;
@AutoWired
默认是通过byType
的方式,如果类型一致,再通过byName
的方式- 如果
byType
和byName
都不行的话就需要通过@Qualifier
来实现,例如下面这种情况
.xml文件
//这种情况是容器有两个Dog类型,所以byType不行,又因为dog1和dog2的名字都不符合byName的方式
//所以必须用 @Qulifier 来指定注入对象的名字
<bean name="dog2" class="com.xu.pojo.Dog"/>
<bean name="dog1" class="com.xu.pojo.Dog"/>
<bean name="cat" class="com.xu.pojo.Cat"/>
<bean name="person" class="com.xu.pojo.Person" >
<property name="name" value="xpc"></property>
</bean>
//java文件
public class Person {
@Autowired
@Qualifier(value = "dog1") //此处注解的使用
private Dog dog;
@Autowired
private Cat cat;
private String name;
- 还有一种解决方式是使用
java
提供的@Resource
注解 【值得注意,方便很多】
//通过 @Resource(name = "dog1") 的方式解决上述问题
public class Person {
@Resource(name = "dog1")
private Dog dog;
@Resource
private Cat cat;
private String name;
使用注解 开发
- 注解创建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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描指定包下面的注解-->
<context:component-scan base-package="com.xu"/>
<!--注解的配置-->
<context:annotation-config/>
</beans>
@Component //加上这个就已经注册了bean
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 属性注入
@Component
public class Person {
@Value("xpc") //此处的注解就是注入属性
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 衍生注解—四个层对应的注解只是名字不一样,但是含义是一样的
@Component
public class Pojo {
}
@Repository
public class Dao {
}
@Service
public class Service {
}
@Controller
public class Controller {
}
- 自动装配
- 上一节已经实现
- 作用域
@Component
@Scope(value = "singleton") //在此处用注解实现作用域的指定
public class Person {
@Value("xpc")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 小结–xml配置和注解的优缺点
- xml是万能的
- 注解语法简单,实现一些简单的东西可以用注解
纯JavaConfig开发,不需要用xml配置
步骤:
- 编写pojo
public class Person {
@Value(value = "xpc")
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
- 编写配置类
@Configuration
public class Configration {
@Bean
public Person getPerson1() {
return new Person();
}
}
- 测试
public class MyTest {
public static void main(String[] args) {
// ApplicationContext context = new AnnotationConfigApplicationContext(Configration.class); //获取context方法1
ApplicationContext context = new AnnotationConfigApplicationContext("com.xu.config"); //获取context方法2
Person person=context.getBean("getPerson2",Person.class);
System.out.println(person.name);
}
}
静态代理模式
- 业务接口
- 真实角色实现业务接口
- 代理角色对真实角色的业务 在不改变原有业务接口和真实角色实现类的基础上 做一些补充业务
//租房业务接口
public interface RentService {
public void rent();
}
//真实角色(房东)实现租房业务
public class HostMan implements RentService{
private String name;
public HostMan() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void rent() {
System.out.println(name+"要租房");
}
}
//再不改变原有租房业务和真实角色实现代码的条件下
//代理真实角色(房东)实现签订合同业务
public class HostManAgent implements RentService{
//导入真实角色,完成原有的业务
HostMan hostMan;
public void setHostMan(HostMan hostMan) {
this.hostMan=hostMan;
}
//还是用的真实角色实现的租房业务
public void rent() {
hostMan.rent();
}
//代理真实角色(房东)实现签订合同业务
public void signPromise() {
System.out.println(hostMan.getName()+"签订了合同");
}
}
//测试
public class User {
public static void main(String[] args) {
HostMan hostMan=new HostMan();
hostMan.setName("xpc");
HostManAgent hostManAgent = new HostManAgent();
hostManAgent.setHostMan(hostMan);
//不仅实现了原有的租房业务。还帮房东实现了签订合同的业务
hostManAgent.rent();
hostManAgent.signPromise();
}
}
动态代理【重点】
- 注意:动态代理的接口不是实现类
//动态代理类的处理程序,反射功能都是他来完成的
public class DynamicHostManProxy implements InvocationHandler {
//传入需要代理的真实角色
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//获取对应类的代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method是通过反射创建相应对象实例后拿到的该对象的方法,传入该对象的类型和方法名,即可调用改方法
Object res=method.invoke(target, args);
return res;
}
}
//实现动态代理
@org.junit.Test
public void Test() {
//真实角色实现
HostMan hostMan=new HostMan();
hostMan.setName("xpc");
DynamicHostManProxy dynamicHostManProxy = new DynamicHostManProxy();
//传入真实角色到动态代理程序中
dynamicHostManProxy.setTarget(hostMan);
//自动生成动态代理类,注意此处类型必须是接口类型,不能是具体的类的类型
RentService proxy=(RentService) dynamicHostManProxy.getProxy(); //动态代理的是接口
//此处调用的过程都由动态代理类处理程序自动处理的
proxy.rent();
}